Scheduling (Cron)
Keep subscription state up to date with periodic sweep jobs.
BirrJS uses cron sweeps to update subscriptions when events don't arrive via webhook — expired periods and stuck pending payments. Chapa doesn't notify on these, so BirrJS handles them locally.
Sweep Jobs
Three maintenance sweeps keep subscription state consistent:
| Sweep | Default interval | What it does |
|---|---|---|
| Reminder | Every day at 8am | Fires subscription.reminder events for subs expiring in [7, 3, 1] days |
| Pending | Every 5 min | Marks pending subscriptions older than the timeout as failed |
| Expiry | Every 10 min | Marks active subscriptions past their period end as expired |
These are purely data updates — no payment operations, no provider API calls.
Scheduling Modes
Auto (default)
Sweeps run inside your application process. Recommended for long-running Node.js/Bun apps.
createBirr({
scheduling: {
mode: "auto",
// Optional overrides:
reminderSweepCron: "0 8 * * *",
reminderLeadDays: [7, 3, 1],
pendingSweepCron: "*/5 * * * *",
expirySweepCron: "*/10 * * * *",
pendingTimeoutMinutes: 60,
},
});| Field | Default | Description |
|---|---|---|
mode | — | Set to "auto" |
reminderSweepCron | 0 8 * * * | Cron expression for reminder check |
reminderLeadDays | [7, 3, 1] | Which days before expiry trigger a reminder. Sub expires June 20 → reminders on June 13, June 17, June 19 |
pendingSweepCron | */5 * * * * | Cron expression for pending check |
expirySweepCron | */10 * * * * | Cron expression for expiry check |
pendingTimeoutMinutes | 60 | Age at which pending subs are marked failed |
Auto mode uses UTC for scheduling, includes overlap guards, and stops sweeps on graceful shutdown.
External
Exposes HTTP endpoints for your own cron service. Best for serverless (Vercel, AWS Lambda, etc.).
createBirr({
scheduling: {
mode: "external",
cronSecret: "your-secret-key",
},
});curl -X POST https://your-app.com/api/birrjs/cron/pending \
-H "Authorization: Bearer your-secret-key"
curl -X POST https://your-app.com/api/birrjs/cron/expiry \
-H "Authorization: Bearer your-secret-key"
curl -X POST https://your-app.com/api/birrjs/send-reminders \
-H "Authorization: Bearer your-secret-key"| Field | Description |
|---|---|
mode | Set to "external" |
cronSecret | Secret key for Bearer auth on cron endpoints |
Manual
No scheduling. Call the sweep functions directly from your own code or scripts.
createBirr({
scheduling: { mode: "manual" },
});
// Run sweeps manually:
await birrjs.checkPendingSubscriptions();
await birrjs.checkExpiredSubscriptions();
await birrjs.sendReminders();Useful for testing, one-off maintenance, or custom scheduling logic.
Mode Comparison
| Auto | External | Manual | |
|---|---|---|---|
| Internal scheduling | ✅ | ❌ | ❌ |
| HTTP endpoints | ❌ | ✅ | ❌ |
| Serverless friendly | ❌ | ✅ | ✅ |
| Long-running apps | ✅ | ❌ | ✅ |
| Reminder sweep | ✅ | ✅ | ✅ |
Cron Syntax
BirrJS uses the standard 5-field cron syntax:
* * * * *
│ │ │ │ └─ Day of week (0-6)
│ │ │ └─── Month (1-12)
│ │ └───── Day of month (1-31)
│ └─────── Hour (0-23)
└───────── Minute (0-59)