Skip to main content
Some work isn’t triggered by a request; it runs on a clock. In this chapter you add a link-sweeper worker that gives every new link an expiry and deletes the stale ones on a schedule with iii-cron. As with the safety agent in Chapter 8, the sweeper stays decoupled from the link worker: it tracks expiry in its own database by subscribing to link.created, and removes expired links through the link::delete you already wrote. The link worker needs no changes.

Add the workers

iii-cron fires functions on a schedule. The link-sweeper worker is yours, so scaffold it the same way you scaffolded link in Chapter 1:

Give the sweeper its own database

The sweeper tracks expiry itself, so it needs somewhere to keep it. Add a sweeper database to the database worker’s config, alongside the ones from earlier chapters:
config.yaml
The worker leverages two other workers: iii-pubsub and iii-cron. First we’ll subscribe to link.created and record an expiry for each new link in the sweeper database. The TTL defaults to 30 seconds so you can watch links expire during the tutorial; in production you’d set SWEEP_TTL_SECONDS to something like a year. Replace the generated link-sweeper/src/index.ts with:
link-sweeper/src/index.ts

Schedule sweeping

Then it sweeps on a schedule: it queries its own table for expired codes (ie. expires_at < TTL), deletes each from the link worker through link::delete, and removes its local entry. The cron expression has seven fields, starting with seconds and ending with year (0 0 3 * * * * is 03:00 every day, any year):
link-sweeper/src/index.ts
Register it with your project:
sweep_expired is an ordinary function, so you can run it on demand to test rather than waiting for the schedule to fire.

See it work

Create a link. The sweeper records a 30-second expiry for it behind the scenes, off the link.created event:
Run the sweep right away and nothing happens, because the 30 seconds haven’t passed:
Wait 30 seconds (the cron also fires every 15 seconds on its own), then resolve the code again: The link has been swept from the link worker:

Conclusion

Linkly now maintains itself: a dedicated link-sweeper worker tracks expiry by subscribing to link.created and deletes stale links on a schedule, all without touching the link worker. That ends the tutorial. You started with a single-worker URL shortener in Chapter 1 and finished with a real system: HTTP, durable storage, an event bus, a queue, a live click stream, bulk uploads over a channel, a browser worker, an autonomous safety agent that investigates links in sandboxes, and scheduled maintenance, all on the same iii bus and all visible in the same console.