ETS as a cache for DB abstraction?


I’m just getting started with Elixir/Ecto and all, so if I’m way off base here please let me know.
It seems that generally ETS is very good for making things go fast. Obviously DB calls can be a source of high latency, and caching DB calls in ETS seems like a generally good idea in certain situations.

Say you have the following:

  1. a dataset that does not change frequently, but is read often.
  2. a dataset who’s size is not ginormous (e.g. easily fits in RAM)

I’m thinking that a good architecture would be to create a GenServer-based ‘Manager’ that exposes:
a) some sort of method that would update the DB
b) call methods to read from DB
Each time the DB is updated or read from, the manager would dump the new data into a :protected ETS table.
The module would also expose cached versions of the read methods, which all follow the general pattern of 1) check ETS, if cache miss then actually call the manager to get updated values from ETS.

As I see it, this design has a couple of nice things about it:

  1. Reads happen predominantly on consumers process from ETS; only rarely actually invoking a GenServer call
  2. Writes to the DB/ETS all can only happen via the manager and so are all in one place, ~controlled.

I guess my question is therefor of 2 parts. 1) Am I missing something here, or is there a better way? and 2) if this is all fine and dandy, this pattern seems sufficiently general/many datasets fit these requirements/ that I’m sure there’s a package somewhere that can better manage this sort of pattern dynamically, can anyone point me in the right direction?



Have you tried cachex? Seems like it’s doing what you need.

1 Like