Scheduled Automation
Per-User Morning Briefing on Trigger.dev
A durable, multi-tenant scheduled task on Trigger.dev that fires each user's morning briefing in their own timezone, assembles calendar/tasks/weather, and delivers it — one task, thousands of schedules.
What It Does
This recipe builds the scheduling backbone for a personal-assistant product where every user gets a morning briefing at their own local time. Instead of one global cron, you define a single Trigger.dev scheduled task and attach a per-user imperative schedule keyed by externalId (the user id) and their timezone. When a user’s schedule fires, the task loads that user, gathers their day (calendar events, due tasks, weather), summarizes it with an LLM, and sends it. Trigger.dev handles retries, queues, observability, and elastic scaling, so a single task can back thousands of users.
The Stack
- Trigger.dev Scheduled Tasks —
schedules.task()defines the briefing job;schedules.create()attaches one schedule per user withcron: "0 7 * * *", the user’stimezone, anexternalId, and adeduplicationKeyso you never double-schedule a user. - TypeScript — the briefing task lives in your
/triggerfolder; thepayloadcarriestimestamp,timezone, andexternalId. - An LLM — summarize each user’s day with a free/BYOK model such as GitHub Models.
- Data sources — your app DB plus the user’s calendar/tasks, fetched inside the run by
externalId.
Step-by-Step Outline
- Define the task —
schedules.task({ id: "morning-briefing", run }); insiderun, readpayload.externalIdand load that user. - Assemble the briefing — fetch the user’s calendar, tasks, and any extras, then summarize with the LLM.
- Deliver — send the briefing (email / push / Telegram) to that user.
- Onboard schedules — when a user signs up, call
schedules.create({ task, cron, timezone, externalId, deduplicationKey })so each user runs at 7am local. - Manage — use
schedules.deactivate/activate/delto pause or remove a user’s briefing without redeploying.
Source
Trigger.dev docs — Scheduled tasks (cron), including dynamic per-user schedules via externalId