     # If there is a cached version of stats (which has given ttl) return that -- this could have
     # been computed by any of the hubs.  If there is no cached version, compute new one and store
     # in cache for ttl seconds.
-    # CONCERN: This could take around 15 seconds, and numerous hubs could all initiate it
-    # at once, which is a waste.
     num_recent_projects: (opts) =>
         opts = defaults opts,
             age_m : required

                                stats.hub_servers = []
                                for x in hub_servers
                                    if x.expire > now
                                        delete x.expire
                                        stats.hub_servers.push(x)
                                cb()
                ], cb)
            (cb) =>
                @table('stats').insert(stats).run(cb)
        ], (err) => opts.cb(err, stats))

    ###
    # Hub servers

            ttl : 60  # how long cached version lives (in seconds)
            cb  : required
        stats = undefined
        dbg = @dbg('get_stats')
        async.series([
            (cb) =>
                dbg()
                @table('stats').between(new Date(new Date() - 1000*opts.ttl), new Date(),
                                           {index:'time'}).orderBy('time').run (err, x) =>
                    if x?.length then stats=x[x.length - 1]
                    cb(err)
            (cb) =>
                if stats?
                    dbg("using recent stats from database")
                    cb(); return
                # if we have stats info from changefeeds use that
                if @_stats
                    dbg("use changefeed stats (insert into db)")
                    stats = @_stats_from_changefeed()
                    @table('stats').insert(stats).run(cb)
                else
                    # will compute from scratch
                    cb()
            (cb) =>
                if stats?
                    cb(); return
                dbg("compute all stats from scratch")
                stats = {time : new Date()}
                async.parallel([
                    (cb) =>
                        @table('accounts').count().run((err, x) => stats.accounts = x; cb(err))
