3
votes

We have a multi-tenant NodeJS application and we are now adding a cache layer for some of our data.

We are aiming to use Redis cache with redis package and we are trying to check our options for supporting multi-tenancy with two main points in mind:

  1. Securing data.
  2. Purging the old data in tenant level.

Our investigation results so far are that we can use separate Redis instances for each tenant - which is not a good solution for us.

Another option we found is to namespace our keys with the "tenant_id:" prefix. This option solves the first point - data is secured now, but we still have the second point to resolve.

Our use case for this point is that one tenant can put a major amount of data which will fill the cache and push out other tenants' data. We want to define our LRU in tenant level, that is - when new data is added to the cache it will evict only the last recently used data of the same tenant.

Any suggestions?

3

3 Answers

4
votes

While the option to use logical/numbered/shared databases certainly exists, you should refrain from doing so. Not only will your databases share the same config, because Redis is single threaded each tenant will (potentially) interfer with the operation of others and (worst case) block them.

What you should do is use a dedicated Redis process for each tenant. The good news is that Redis is quite lightweight, so there is very little overhead for each instance in terms of resources. The slightly less good news is that this approach will make administration more complex.

If you wish to avoid the admin pain, I recommend that you research the option of using a hosted Redis offering. Depending on your provider, some allow creating multiple dedicated instances at no extra cost.

Disclaimer: I work at Redis Labs, the home of Redis and provider of solutions, including a hosted Redis that behaves like I described above (for that exact purpose btw).

0
votes

Have you investigated using separate Redis logical databases for every tenant?

You can switch the active database with the SELECT command or select the database to use (database-id) when connecting to your Redis instance:

redis://user:password@host:port/database-id

For instance:

redis://user:password@localhost:6379/1

to connect to logical database 1.

0
votes

I just stumbled across the same question and found a good solution.. Look in KeyDB (https://keydb.dev/), it's a Redis fork and now supports multithreading. It's fully compatible with Redis, a drop-in replacement for Redis; so you don't have to change any code.

I use it as full text search provider in a multi-tenancy scenario. My data store is MongoDB (has less support for fts); Every tenant has a hash list in KeyDB storing all keywords. Then HSCAN is used to query KeyDB (it's really fast). The results can then be resolved by MongoDB. Since KeyDB is non-blocking and multi-threading there is no need for complex deployment solutions.

And yes, you can use the existing nodejs libs for Redis to access KeyDB.

Stay healthy, best!