Extremly simplistic time-based Counters in Redis redis = Redis.connect counter = TimedCounter.new(redis) counter.reset!(:test) counter.incr(:test, 1) # get the last 5 minutes # returns [0, 0, 0, 0, 1] p counter.minutes(:test, 5.minutes.ago, 5) # get the last 60 minutes p counter.minutes(:test, 1.hour.ago, 60) # get the last 30 days p counter.days(:test, 30.days.ago, 30) Data is kept in Hashes in Redis (mostly to cut down on key sizes) per Key you'll get: - one total value - one years hash with a field per year eg. { 2010: value, 2011: value } - one hash per years with a field per month { 01: value, ...} - one hash per month with a field per day - one hash per day with a field per hour - one hash per hour with a field per minute Key Layout is: $tc:<key>:<timestamp part> Keys given may be arrays and will be joined with "/". eg. [:user, 1, :clicks] == "user/1/clicks" Currently does not set any expires, probably should add some depending on the amount of counts kept. Might be sensible to delete the hour hashes after a few days. Performs all increments atomically instead of relying on rollups and other services. No Idea how well this scales, but should be able to increment a couple thousand counters per second. Redis Monitor Log: 1299922276.799784 "multi" 1299922276.800636 "incrby" "$tc:test:1:total" "1" 1299922276.800728 "hincrby" "$tc:test:1:years" "2011" "1" 1299922276.800762 "hincrby" "$tc:test:1:2011" "03" "1" 1299922276.800789 "hincrby" "$tc:test:1:201103" "12" "1" 1299922276.800817 "hincrby" "$tc:test:1:20110312" "10" "1" 1299922276.800837 "hincrby" "$tc:test:1:2011031210" "31" "1" 1299922276.800899 "exec" A hopefully accurate set of all counters keys is kept in "$tc_list" ("SMEMBERS $tc_list").