                     age_m = 999999999999  # 'infinite'
                 if age_m > interval
                     # will make this snapshot
-                    todo.push("#{misc.to_iso_path(now)}-#{name}")
-            dbg("snapshots to make: #{todo}")
-            if todo.length > 0
+                    to_create.push("#{misc.to_iso_path(now)}-#{name}")
+                # Are there two many snapshots of the given type?  If so, delete them
+                for s in v.slice(opts[name])
+                    to_delete.push(s)
+            cb()
+        (cb) ->
+            dbg("snapshots to make: #{to_create}")
+            if to_create.length > 0
                 f = (snap, cb) ->
                     make_snapshot(opts.filesystem, snap, cb)
-                async.map(todo, f, cb)
+                async.map(to_create, f, cb)
+            else
+                cb()
+        (cb) ->
+            dbg("snapshots to delete: #{to_delete}")
+            if to_delete.length > 0
+                f = (snap, cb) ->
+                    delete_snapshot(opts.filesystem, snap, cb)
+                async.map(to_delete, f, cb)
             else
                 cb()
     ], (err) -> opts.cb?(err))

    opts = defaults opts,
        filesystem : required
        five       : 12*10  # number of five-minute snapshots to retain
        hourly     : 24*7   # ...
        daily      : 30
        weekly     : 20
        monthly    : 12
        cb         : undefined
    dbg = (m) -> winston.debug("snapshot: #{m}")
    dbg()
    snapshots = undefined
    async.series([
        (cb) ->
            dbg("get list of all snapshots")

        (cb) ->
            dbg("got snapshots: #{misc.to_json(snapshots)}")
            # determine which snapshots we need to make
            now = new Date()
            for name, interval of INTERVALS
                # Is there a snapshot with the given name that is within the given
