How to implement realtime count of registered users?

Hello, I Will be releasing my new web soon, or at least I hope :sweat_smile: One feature that I think woud be cool to have for the release is to have a realtime count of registered users somewhere on the web
What is the best way to do this kind of thing (LiveView, Pressence or maybe Channels?) Also how expensive is it for the database If i have to run query enerytimes new user get registered, Im not expecting many users but still.

Thank you for help.

Presence will keep track of your users
 And no db is involved.

But You need to hook this to the frontend, with channels or liveview.

3 Likes

Querying the database to retrieve this kind of information each time a user visits the page is, from my point of view, rarely a good idea.

Personally I would created a GenServer to store the number of registered users in its state (or ETS if you’re really looking for performance).
As soon as the GenServer is created, in a callback handle_continue/2 you make a first request to the database to get the current number of registered users and you store this as the initial state. Then at each new registrant you will call this process and ask it to increment its state.

2 Likes

Rather than building your own GenServer cache, I would simply use Cachex: https://github.com/whitfin/cachex/

2 Likes

This is also what I use when I need a cache that has to manage a large number of keys/values or when I need more advanced features such as key expiration etc

But I figured since the author was just trying to manage a single value and increment it, it might be a bit overkill to use an dependency for that.

That’s why I recommended a simple GenServer

2 Likes

I read/interpret your requirement as you want to show how many users are registered, meaning the amount of records you have in your database of users registered. If that’s the case it’s perfectly valid to just do a standard SQL query on your database and count the records every page view. Most databases don’t break a sweat.
The idea behind it would be; Make it work, Make it right, Make it fast. In that order. (I believe this is coming from Kent Beck). I guess you can also add; while making it work, keep it as simple as possible at first.

A database can do 100s of queries per second, most of the time it can even keep your query ‘hot’ in memory as if you’re using a key value store like redis. If it actually becomes a problem you can make it fast by caching. But now you have another problem; cache invalidation, because if you have 2 app servers you have to coordinate the cache invalidation.

Finally when making it fast, please measure! (i have just replaced a very “fast” piece of code in ETS replaced with normal elixir maps which seem to be faster after actually measuring)

If the above interpretation of your question is not correct and the question is more about ‘live’ users visiting your website then it would be better to directly go for presence as this is better suited for that use case.

Have fun while coding!

(EDIT: just to give you an idea, look at these numbers: https://www.techempower.com/benchmarks/#section=data-r18&hw=ph&test=db they show you how fast a DB can be on top of beefy hardware. And it’s not even that expensive you can rent this kind of hardware with ovh or hetzner for around 70-100 usd per month.)

1 Like

I think a combo of Presence (which might be too heavy, could just use a normal Channel) and a shared mnesia schema is a good way to go. It has the benefit of being consistent across the nodes if you have clustering already setup. Its not perfect, due to net splits and other consistency issues, but it can be done ‘easily’ using dirty_update_counter/3 on connection setup / cleanup. You can run mnesia using ram_copies to prevent disk writes and ensure speed.

This is a really good resource on mnesia and how to get it setup.

Best of luck.

After some research I also come to this conclusion. Just simple count on user database is enough. I Will show it on registration template. Thanks for asistance :slightly_smiling_face:

1 Like