Running one Redis per VPS is a perfectly reasonable call for small-to-medium projects. The trouble starts when several apps begin sharing the same instance: one project’s users key clobbers another’s users key, and the moment someone runs FLUSHALL everyone goes down.

The fix isn’t standing up a new Redis; it’s namespace discipline.

A three-layer key scheme

In production I use this pattern:

<env>:<app>:<bounded-context>:<key>

For example:

prod:billing:invoice:42
prod:auth:session:1c2f...
staging:notify:queue:retry

Having all three layers buys you two things:

  1. Clarity when searching. With redis-cli --scan --pattern 'prod:billing:*' I can see the keys of just one project.
  2. Friction against accidental deletes. I think twice when I type redis-cli --scan --pattern 'staging:*' | xargs redis-cli DEL instead of FLUSHDB.

Don’t rely on logical DBs

Redis has logical DBs numbered 0–15, but in a word: don’t use them. Three reasons:

  • The SELECT command is scoped only to that connection — chaos in a connection pool.
  • Some libraries don’t support a DB switch inside MULTI/EXEC blocks.
  • Redis Cluster doesn’t support logical DBs at all; the day you move to a cluster, every one of your assumptions collapses.

Learning and applying a namespace prefix is the only approach.

Connection-level isolation

If you’re on Laravel, define a separate Redis connection per app in config/database.php and bake the namespace into the connection with prefix:

'redis' => [
    'billing' => [
        'host' => env('REDIS_HOST'),
        'password' => env('REDIS_PASSWORD'),
        'port' => env('REDIS_PORT', 6379),
        'database' => 0,
        'prefix' => 'prod:billing:',
    ],
    'auth' => [
        // ...
        'prefix' => 'prod:auth:',
    ],
],

Now a Redis::connection('billing')->set('invoice:42', ...) call automatically writes prod:billing:invoice:42. Even if a developer forgets to write the namespace by hand, the system protects itself.

Disable the dangerous commands

In redis.conf it’s a good idea to rename or disable these commands in production:

rename-command FLUSHDB ""
rename-command FLUSHALL ""
rename-command KEYS ""

KEYS matters most — it blocks the event loop for the whole scan, and every other client waits behind it. Redis’s own docs put a 1M-key database at about 40 ms on an entry-level laptop, so on a 100k-key instance you’re talking milliseconds — but the cost grows with the keyspace, and on multi-million-key instances the stall gets long enough to hurt. Using SCAN instead should be mandatory.

When do you drop this pattern?

Move to separate Redis instances if any one of three signals shows up:

  1. One project’s traffic measurably affects the latency of the others.
  2. One project wants persistent storage (RDB/AOF) while the others are cache-only.
  3. One project needs a different Redis version or feature.

Before any of those, hold to this simple rule: writing a prefix is cheaper than starting a new process.