Best Practice: Automatic session timeout/cleanup?

I'm developing an application where I need to have all sessions that have been inactive for X minutes (in this case, I'm thinking 10 minutes, but I'm flexible to a point) automatically purged from the database (using ActiveRecord session store).

What I've done is created a simple rake task that just looks at the updated_at column and deletes anything older than 10 minutes. I plan to have a cron task run this job every 10 minutes. In theory, this should keep inactive sessions to a minimum and clean up my database sessions at the same time automatically, keeping the number in the table at any given time fairly low.

However, I'm concerned that running a rake task every 10 minutes could have some performance issues. Does anybody have any feedback on this? Is this generally considered "OK" or is there a better way (that also can purge old sessions automatically)?

What is your motivation for removing these rows at all? Generally, large database tables that are properly indexed shouldn’t pose much of a performance concern.

This is something I've been looking into (but not implemented) and the problem with this approach seems to be the startup overhead of loading your Rails environment over and over.

So you might want to look at the various daemon options, i.e. just run something continuously to periodically expunge old sessions.

FWIW,

Well, what you are both looking at doing is:

Session.delete_all, :conditions => ['updated_at < ?', 10.minutes.ago]

That translates into a pretty quick database query, depending on the number of sessions you anticipate having. WDYT?

Right, finding old sessions isn't the hard part :slight_smile:

The question is rake via cron/equiv versus background task.

Speaking only for myself, I'd need to run this much more often, say every 2 or 3 minutes, and do related cleanup tasks as part of session removal, meaning this would require most of the Rails environment.

What is your motivation for removing these rows at all? Generally, large database tables that are properly indexed shouldn't pose much of a performance concern.

The reasoning behind this is that I want old sessions that are inactive for 10 minutes to be terminated automagically. It's a "security" concern (notice the quotes - intentional :slight_smile: ). This is a workplace-only application for our employees to use. Theoretically, there's no reason that a user's session, that has been idle for 10+ minutes, should have access without logging in again. This will be seen by customers in our retail stores, and I don't necessarily want all this data just "available" in the event one of our sales associates walks away from a computer, and a customer starts poking around for no good reason. Obviously that's not "great" security, but it's "Good Enough(TM)".

Company-wide we only have roughly ~350 employees, so the size of the DB has never been a major concern for me. I was more curious about the implications of, as Hassan pointed out, loading the Rails environment every 10 minutes. I was actually thinking more along the lines of memory leaks (even a very small one could snowball very fast on a 10-minute cron job), but Hassan's point is more...to the point.

This is something I've been looking into (but not implemented) and the problem with this approach seems to be the startup overhead of loading your Rails environment over and over.

So you might want to look at the various daemon options, i.e. just run something continuously to periodically expunge old sessions.

Thanks. This is exactly the kind of stuff I was worried about, and I appreciate you bringing up a point I was probably just too tired to see :slight_smile: Do you have any thoughts/ideas on a daemonized version that I could run as a rake task? I've never written a real daemon before - in any language - so I'm not sure even where to start. Are there any gems that would be useful in the process?

Well, what you are both looking at doing is:

Session.delete_all, :conditions => ['updated_at < ?', 10.minutes.ago]

That translates into a pretty quick database query, depending on the number of sessions you anticipate having. WDYT?

Yep, that's essentially what my rake task does right now. It's just that the cost of loading the Rails environment once every 10 minutes (as a cron job would do) would be a bit too costly, as Hassan points out. A daemonized version of that is probably the way to go.

Thank you all for your help :slight_smile:

Hello--

What is your motivation for removing these rows at all? Generally, large database tables that are properly indexed shouldn't pose much of a performance concern.

The reasoning behind this is that I want old sessions that are inactive for 10 minutes to be terminated automagically. It's a "security" concern (notice the quotes - intentional :slight_smile: ). This is a workplace-only application for our employees to use. Theoretically, there's no reason that a user's session, that has been idle for 10+ minutes, should have access without logging in again. This will be seen by customers in our retail stores, and I don't necessarily want all this data just "available" in the event one of our sales associates walks away from a computer, and a customer starts poking around for no good reason. Obviously that's not "great" security, but it's "Good Enough(TM)".

Company-wide we only have roughly ~350 employees, so the size of the DB has never been a major concern for me. I was more curious about the implications of, as Hassan pointed out, loading the Rails environment every 10 minutes. I was actually thinking more along the lines of memory leaks (even a very small one could snowball very fast on a 10-minute cron job), but Hassan's point is more...to the point.

This is something I've been looking into (but not implemented) and the problem with this approach seems to be the startup overhead of loading your Rails environment over and over.

So you might want to look at the various daemon options, i.e. just run something continuously to periodically expunge old sessions.

Thanks. This is exactly the kind of stuff I was worried about, and I appreciate you bringing up a point I was probably just too tired to see :slight_smile: Do you have any thoughts/ideas on a daemonized version that I could run as a rake task? I've never written a real daemon before - in any language - so I'm not sure even where to start. Are there any gems that would be useful in the process?

Well, what you are both looking at doing is:

Session.delete_all, :conditions => ['updated_at < ?', 10.minutes.ago]

That translates into a pretty quick database query, depending on the number of sessions you anticipate having. WDYT?

Yep, that's essentially what my rake task does right now. It's just that the cost of loading the Rails environment once every 10 minutes (as a cron job would do) would be a bit too costly, as Hassan points out. A daemonized version of that is probably the way to go.

Thank you all for your help :slight_smile:

I'm developing an application where I need to have all sessions that have been inactive for X minutes (in this case, I'm thinking 10 minutes, but I'm flexible to a point) automatically purged from the database (using ActiveRecord session store).

However, I'm concerned that running a rake task every 10 minutes could have some performance issues.

This is something I've been looking into (but not implemented) and the problem with this approach seems to be the startup overhead of loading your Rails environment over and over.

So you might want to look at the various daemon options, i.e. just run something continuously to periodically expunge old sessions.

FWIW, --

Well, what you are both looking at doing is:

Session.delete_all, :conditions => ['updated_at < ?', 10.minutes.ago]

That translates into a pretty quick database query, depending on the number of sessions you anticipate having. WDYT?- Hide quoted text -

Out of curiosity, is there a reason the cookie-based sessions would not work for you? These auto-clean and don't clutter up your database. For your security timeout, I'd suggest something like this:

# application.rb (or application_controller.rb if it's a new rails app)

   around_filter :check_auto_logout # This needs to be run first to make sure we don't have stale expired sessions

   def check_auto_logout      begin        if logged_in? && current_user.is_parent? && session[:session_expiry] && session[:session_expiry] < Time.now          session[:user_id] = nil # could remove a database row, if need be        end      rescue ActiveRecord::RecordNotFound # Handle stale session cookie problems.        session[:user_id] = nil      end

     yield

     session[:session_expiry] = Rails.env.development? ? 1.hour.since : 5.minutes.since    end

Out of curiosity, is there a reason the cookie-based sessions would not work for you? These auto-clean and don't clutter up your database. For your security timeout, I'd suggest something like this:

Not being the OP, this is a bit of a hijack, but... :slight_smile:

around_filter :check_auto_logout # This needs to be run first to make sure we don't have stale expired sessions

This seems like it would fit the OP's use case, but not mine, in that it depends on another request coming in after the session timeout period has expired.

Would you have a suggestion on cleanup of abandoned sessions?

Here's my use case:

Web site sells unique/limited quantity items. User puts item in cart; item is now unavailable to other users. User abandons cart (stops interacting with site for 30 minutes) Cart is "emptied", item is returned to inventory.

Interested in any ideas on the most Rails-ish way to handle this.

> Out of curiosity, is there a reason the cookie-based sessions would > not work for you? These auto-clean and don't clutter up your database. > For your security timeout, I'd suggest something like this:

Not being the OP, this is a bit of a hijack, but... :slight_smile:

> around_filter :check_auto_logout # This needs to be run first > to make sure we don't have stale expired sessions

This seems like it would fit the OP's use case, but not mine, in that it depends on another request coming in after the session timeout period has expired.

Would you have a suggestion on cleanup of abandoned sessions?

Here's my use case:

Web site sells unique/limited quantity items. User puts item in cart; item is now unavailable to other users. User abandons cart (stops interacting with site for 30 minutes) Cart is "emptied", item is returned to inventory.

Well presumably in your case you have to track the fact that this item is now locked or whatever in the database. Make it so that such locks are updated while the user keeps using the site and have a cronjob that expires locks from users that have not been active since X. Another possibility is to have a locked_until field, in which case you don't need to clear out the lock at all.

Fred

Web site sells unique/limited quantity items. User puts item in cart; item is now unavailable to other users. User abandons cart (stops interacting with site for 30 minutes) Cart is "emptied", item is returned to inventory.

Well presumably in your case you have to track the fact that this item is now locked or whatever in the database. Make it so that such locks are updated while the user keeps using the site and have a cronjob that expires locks from users that have not been active since X.

Yeah, it's the cronjob aspect that seems extremely clunky to me, but that could be a background task.

Another possibility is to have a locked_until field, in which case you don't need to clear out the lock at all.

Ah, interesting approach. Since that would have to be updated on each subsequent request by that user, what would be the DRYest way to trigger the update?