Surplus logo
Surplus Docsby Sharing Excess
The Stack

Cron workers

The crons/ directory holds scheduled jobs that run independently of the API server. Each is its own Bun program with its own Dockerfile and Railway configuration, scheduled with a cronSchedule in railway.json.

The jobs

analyticsCache

Warms the analytics cache so dashboards stay fast. It acquires a Redis lock (so overlapping runs don't collide), queries the read replica through AnalyticsService, and writes the results into Redis.

  • Schedule: */15 0,1,2,12-23 * * * — every 15 minutes during active hours, skipping the quiet overnight window.

postgresBackup

Takes a logical backup of the primary database: it runs pg_dump, gzips the output, and uploads it to a private S3 backups bucket.

  • Schedule: 0 5 * * * — once daily.

fileStorageBackup

Mirrors the primary file-storage bucket to a separate backup bucket — copying new or changed objects and removing orphans — so uploaded files have a second, independent copy.

  • Schedule: 0 5 * * * — once daily.

recurringSchedules

A placeholder for future scheduled work. It has no implementation yet.

How they run

Each cron is deployed to Railway as its own service with restartPolicyType: NEVER — the job runs to completion on its schedule rather than staying resident. They build from their own Dockerfiles (crons/<name>/Dockerfile) using the monorepo as the build context, so they can import the same shared packages the API server uses.

Because they reuse @surplus/services, @surplus/postgres, and @surplus/redis, the cron jobs benefit from the same domain logic and database access patterns as the rest of the platform — they just inject their own clients and run headless.