# Switching between 2 ETS tables for caching

**URL:** <https://erlangforums.com/t/switching-between-2-ets-tables-for-caching/2070>\
**Category:** Questions / Help\
**Tags:** ets\
**Created:** [November 24, 2022, 6:47am UTC](https://erlangforums.com/t/switching-between-2-ets-tables-for-caching/2070 "2022-11-24T06:47:12Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![zabrane](https://erlangforums.com/letter_avatar_proxy/v4/letter/z/7ba0ec/32.png) [@zabrane](https://erlangforums.com/u/zabrane)\
**Post date:** [November 24, 2022, 6:47am UTC](https://erlangforums.com/t/switching-between-2-ets-tables-for-caching/2070/1 "2022-11-24T06:47:12Z")

</div>

Hi there,

I’ve got 02 ETS tables and would like to switch between them atomically. Let me explain:

Tab1: contains latest cached data  
Tab2: contains old cached data

After a certain period of time, id like to apply this logic:

1. delete Tab2 completely (maybe optional)
2. rename Tab1 as Tab2
3. create an empty Tab1

Between step 2 and 3, i might receive queries hitting Tab1 which doesn’t exist yet. And hence my problem.

Can I make the above steps look atomic?  
If yes, can I generalize the idea to more than 02 tables?

Thanks  
/Zab

---

<div class="post-metadata">

**Author:** ![max-au](https://erlangforums.com/user_avatar/erlangforums.com/max-au/32/1627_2.png) [@max-au](https://erlangforums.com/u/max-au)\
**Post date:** [November 24, 2022, 7:37am UTC](https://erlangforums.com/t/switching-between-2-ets-tables-for-caching/2070/2 "2022-11-24T07:37:34Z")

</div>

There are two approaches known to me:

1. Keep both “latest” (usually called “active”) and “old” in the same table, wrapping the original key in a tuple of `{TabName, Key}`. It’s also often extended to the concept of the [“striped table”](https://www.erlang.org/blog/persistent_term/).
2. Store active table name in the persistent\_term, so fetching data from the cache looks like `ets:lookup(persistent_term:get(active_table_name), Key)`. When you’re about to swap the tables, just call `persistent_term:put(active_table_name, NextTableName)`.

Of course both approaches are easy to generalise.

Unfortunately there is no atomic `swap` operation swapping two names ETS tables. It might be worth adding it, it appears to be a common ask for OTP.

---

<div class="post-metadata">

**Author:** ![juhlig](https://erlangforums.com/user_avatar/erlangforums.com/juhlig/32/837_2.png) [@juhlig](https://erlangforums.com/u/juhlig)\
**Post date:** [November 24, 2022, 9:32am UTC](https://erlangforums.com/t/switching-between-2-ets-tables-for-caching/2070/3 "2022-11-24T09:32:40Z")

</div>

You must already have a process that owns the tables and handles the turnover, right? So what I would do here is try to query Tab1. If that fails because Tab1 is currently missing, meaning turnover is happening just at that moment, send a message to and wait for a reply from the owning process. The owning process should (receive and) reply to such messages only after it has finished the turnover, meaning Tab1 will be there again, and the querying process can try accessing Tab1 again.

Depending on how the cache is used (query frequency, turnover frequency, …), this waiting may actually defeat the entire purpose of having a cache in the first place, so it could also be possible to just proceed as if the queried value was not present in the cache at all on failure.

---

<div class="post-metadata">

**Author:** ![NelsonVides](https://erlangforums.com/user_avatar/erlangforums.com/nelsonvides/32/1205_2.png) [@NelsonVides](https://erlangforums.com/u/NelsonVides)\
**Post date:** [November 24, 2022, 10:24am UTC](https://erlangforums.com/t/switching-between-2-ets-tables-for-caching/2070/4 "2022-11-24T10:24:41Z")

</div>

That is exactly what this caching library already implements: [GitHub - esl/segmented\_cache: Modern, performant, and extensible, Erlang in-memory cache](https://github.com/esl/segmented_cache), hopefully you can already just use it. Disclaimer, I’m the author 😄 )

How to make it look atomic, and generalised to more than one table? Keep an [atomic](https://www.erlang.org/doc/man/atomics.html) in a persistent term that points to the current table to start from. Then querying processes will read that atomic and cycle through the ets tables starting at the index the atomic points to. A background process periodically increments the atomic (in a rotatory way), and cleans up whatever was there in the table that is now considered last after rotation.

---

<div class="post-metadata">

**Author:** ![zabrane](https://erlangforums.com/letter_avatar_proxy/v4/letter/z/7ba0ec/32.png) [@zabrane](https://erlangforums.com/u/zabrane)\
**Post date:** [November 24, 2022, 7:19pm UTC](https://erlangforums.com/t/switching-between-2-ets-tables-for-caching/2070/5 "2022-11-24T19:19:12Z")

</div>

Thank you guys. Exactly what i was looking for.

---

<div class="post-metadata">

**Author:** ![tsloughter](https://erlangforums.com/user_avatar/erlangforums.com/tsloughter/32/418_2.png) [@tsloughter](https://erlangforums.com/u/tsloughter)\
**Post date:** [July 23, 2023, 9:40pm UTC](https://erlangforums.com/t/switching-between-2-ets-tables-for-caching/2070/6 "2023-07-23T21:40:57Z")

</div>

Just happened across this old thread and thought I’d mention the implementation we have in OpenTelemetry: [https://github.com/open-telemetry/opentelemetry-erlang/blob/main/apps/opentelemetry/src/otel\_batch\_processor.erl#L77](https://github.com/open-telemetry/opentelemetry-erlang/blob/main/apps/opentelemetry/src/otel_batch_processor.erl#L77)

It uses a persistent term to store the atom name of the table so it can switch them (there is no GC because an atom is 1 word).

An operation in ETS would be very useful though.
