You can keep track of active users in memory without it being a global variable. It can simply be a module level variable. This is one of the advantages of the nodejs module system.
The reasons to put it in a database instead of memory are:
- You have multiple servers so you need a centralized place to put the data
- You want the data stored persistently so if the server is restarted (normally or abnormally) you will have the recent data
The reasons for not putting it directly in a database:
- It's a significant load of new database operations since you have to update the data on every single incoming request.
- You can sometimes get the persistence without directly using a database by logging the access to a log file and then running chron jobs that parse the logs and do bulk addition of data to the database. This has a downside in that it's not as easy to query live data (since the most recent data is sitting in databases and hasn't been parsed yet).
For an in-memory store, you could do something like this:
// middleware that keeps track of user access let userAccessMap = new Map(); app.use((req, res, next) => { // get userId from the cookie (substitute your own cookie logic here) let id = id: req.cookie.userID; let lastAccess = Date.now(); // if you want to keep track of more than just lastAccess, // you can store an object of data here instead of just the lastAccess time // To update it, you would get the previous object, update some properties // in it, and then set it back in the userAccessMap userAccessMap.set(id, lastAccess); next(); }); // routinely clean up the userAccessMap to remove old access times // so it doesn't just grow forever const cleanupFrequency = 30 * 60 * 1000; // run cleanup every 30 minutes const cleanupTarget = 24 * 60 * 60 * 1000; // clean out users who haven't been here in the last day setInterval(() => { let now = Date.now(); for (let [id, lastAccess] of userAccessMap.entries()) { if (now - lastAccess > cleanupTarget) { // delete users who haven't been here in a long time userAccessMap.delete(id); } } }, cleanupFrequncy); // Then, create some sort of adminstrative interface (probably with some sort of access protection) // that gives you access to the user access info // This might even be available in a separate web server on a separate port that isn't open to the general publoic app.get("/userAccessData", (req, res) => { // perhaps convert this to a human readable user name by looking up the user id // also may want to sort the data by recentAccess res.json(Array.from(userAccessMap)); });