Cron or deferred?
- Cron — repeats on a fixed schedule (every day at 9:00). Defined in code.
- Deferred — happens once, at a time computed at runtime (24 hours after this order). Booked from the handler or from the HTTP request.
Book from the handler
ctx.jelou.schedule() books a run relative to “now”:
index.ts
Parameters
Durations accept compound units from largest to smallest:
"1h30m" is valid, "30m1h" is not.
Absolute time
ctx.jelou.scheduleAt() takes a date instead of a duration:
schedule().
Avoid duplicates
If the service calling your function retries,idempotencyKey guarantees a single booking:
idempotencyKey with a different payload returns a 409 error.
Book from an HTTP request
Any caller can defer a call by adding a header to the normal POST. Without schedule headers, the function runs immediately as always.
The response is
202 Accepted when the booking is created and 200 OK when a retry reuses an existing booking. The body cannot exceed 64 KB.
Receive the fire
When the time comes, your function receives the originalpayload at the path you specified. Use ctx.isScheduledFire to tell the fire apart from a normal request:
Check before acting
Between booking and firing, reality can change: the customer already paid, the template got paused, the user opted out.ctx.guard chains those checks and skips the send if any of them fails:
.run() executes and its result is the response. If any fails, the chain short-circuits and returns { skipped: "<name>" } without running the send.
The chain terminates with
.run(handler), not .then(). ctx.guard is a fresh chain on every request.Look up what is booked
ctx.jelou.findDeferred() lists your function’s pending runs:
Cancel
ctx.jelou.cancelDefer() cancels in bulk by audience or tag. Exactly one of subject, key or keyPrefix is required:
raced holds the runs that were already firing when the cancel arrived — for those, the ctx.guard check inside the handler is the last line of defence. Write your handlers to be idempotent.
Before a broad cancellation, preview the scope with dryRun:
There is no “reschedule”: a booking is immutable. To change the time, cancel and book again.
Local testing
schedule, scheduleAt, findDeferred and cancelDefer only work in a deployed function. Locally they throw because there are no platform credentials.
To exercise the flow with jelou functions dev, turn on simulation:
createMockContext, whose ctx.jelou records the calls with no network or setup.
Inspect from the CLI
Limits
Bookings that already fired, were cancelled or failed do not count against the active limit.
Common problems
- It never fired
- It sent even though I cancelled
- Error in local dev
- It booked twice
Check the booking’s status and last error:If the status is
failed, the error field says why delivery failed. If it is cancelled, something cancelled it first — review your cancelDefer calls.Cron
Recurring tasks on a fixed schedule.
Messaging
Send WhatsApp and validate templates.
Webhooks
Verify signatures from external services.
CLI
The
defer list and defer get commands.