Skip to Content
sesameSend

Vercel and background jobs

Deploy the app, and run the six per-minute jobs on Vercel Pro or on any always-on machine.

Deploy to Vercel

Finish Supabase and AWS first, including the bootstrap step. Then add every variable from .env.example in the Vercel project settings.

Trim every value

Trailing spaces and newlines in env vars cause silent 401s. From the CLI use echo -n "VALUE" | vercel env add NAME production.

Set PUBLIC_BASE_URL to the production origin, for example https://mail.example.com. pnpm build regenerates the route table itself.

The six jobs

Six endpoints under /internal/* do the async work. They need a bearer CRON_SECRET and must be hit every minute.

EndpointDoes
/internal/events/pollReads SES events from SQS
/internal/scheduled/dispatchSends scheduled emails
/internal/webhooks/deliverDelivers and retries webhooks
/internal/broadcasts/dispatchSends broadcasts
/internal/automations/runRuns automation steps
/internal/inbound/pollReads inbound mail

Option 1: Vercel Pro

vercel.json already declares all six as per-minute crons. Nothing else to do. Per-minute schedules need Vercel Pro.

Option 2: Hobby, or any other host

Vercel Hobby allows one cron run per day, and a per-minute schedule makes the deploy fail. Remove the crons array from vercel.json before deploying, then run the jobs from any always-on machine:

OPENSEND_URL=https://mail.example.com CRON_SECRET=... node scripts/cron-runner.mjs

It loops forever. --once does one pass and exits. CRON_INTERVAL_MS changes the 60-second cadence. It never stacks calls on a slow endpoint.

Service templates ship in the repository: docs/cron-runner.plist (launchd, macOS) and docs/cron-runner.service (systemd).

Self-host without Vercel

pnpm build && pnpm start

Run it behind any reverse proxy with the same environment variables, and run scripts/cron-runner.mjs on the same box.