Public ETS / Shared across processes


I’m trying to make some ETS table accessible from multiple processes and I don’t see what I’m doing wrong…

iex(1)> spawn fn ->, [:bag, :public, :named_table]) end
iex(2)> :ets.tab2list(:test)                                          
** (ArgumentError) argument error
    (stdlib) :ets.match_object(:test, :_)
    (stdlib) ets.erl:763: :ets.tab2list/1

→ doesn’t work, while :

 iex(2)>, [:bag, :public, :named_table])                
iex(3)> :ets.tab2list(:test)                          

… works.



line 1 spawns a process so its work is happening asynchronously. This means that it’s possible fore line 2 to run before the ets table is actually created.

EDIT: @nicd also points out that the ets table could also be dead, which is another great point. Basically, the ets table is only alive for an incredibly brief period of time, and it’s quite possible that your tab2list will happen before or after that time.


The process you spawned is the owner of the ETS table. When the process ends (right after it created the table), the table will be deleted. You will need to keep a GenServer that keeps the table alive or transfer ownership to another process. You can also set an heir that inherits the table when the owning process dies.


Don’t Lose Your ets Tables


What others said, also if you want to just have a stupid simple global ETS table that lives as long as your VM lives here’s how to do that (don’t do that in production though):

  defp get_table() do
    if == :undefined do, [:public, :named_table])
      :ets.give_away(@table, get_lively_pid(), nil)
      # avoid races

  defp get_lively_pid() do    
    spawn(fn -> Process.sleep(:infinity) end)

you can then do stuff like :ets.first(get_table()) etc.

1 Like

Or if you want to put this into broader use then have one process which owns all the tables.


There are many wonderful suggestions but I’m curious why you need this ets table accessible from multiple processes. It sounds like using ets as a gasp global variable.

ets doesn’t support transactions, does read/write collisions matter ? Data in ets doesn’t survive a reboot nor is it distributed. Are these something you need ?

Usually after some prodding we realize that mnesia is a better fit.


Thank you all for your answers, I thought “:public” would be enough / I mixed access and process ownership.

As for why use ETS here, it is to do some RAM prefetching, before assembling data, in some context where transactions are not needed (this isn’t live data and data is heavily partitionned) so I think ETS is a good fit. It would also be a bit faster than in-memory Mnesia.

1 Like