{
  "id": 17889068,
  "title": "Webhook Follow-Up Task Scheduling: One Hour Later with Queues or Cron Explained",
  "url": "https://urgent.news/2026/11/03/webhook-follow-up-task-scheduling-one-hour-later-with-queues-or-cron",
  "topic": "tech",
  "section": "Tech",
  "published": "2026-11-03T01:41:56.000Z",
  "source": {
    "name": "Dev.to",
    "slug": "dev-to",
    "url": "https://dev.to/siegfriedfletcher5869/webhook-follow-up-task-scheduling-one-hour-later-with-queues-or-cron-explained-26fb"
  },
  "original_language": "en",
  "account": "When scheduling a webhook follow-up task to run approximately one hour later, using a durable delayed queue or per-event cron entry are two common approaches. However, each has its own set of advantages and drawbacks.\n\nFor a logistics webhook requiring an hourly delay, it is recommended to store the event ID, action, intended run time, attempt count, and a deduplication key in a single transaction alongside the business update. This ensures the follow-up task is recorded in a durable state. The webhook can then return a success response to the carrier without performing the slow follow-up immediately.\n\nTo implement this, create a `FollowUp` table with fields for event ID, kind, runAt timestamp, attempts, and dedupeKey. A poller can then claim ready rows using short batches, leveraging PostgreSQL's `FOR UPDATE SKIP LOCKED` to prevent concurrent workers from claiming the same row. The actual task should be executed outside the database transaction to avoid blocking the transaction.\n\nImplement a claimReady function to retrieve ready rows based on the desired batch size. This function should consider factors such as queue age, claim duration, downstream response time, retry count, and the number of ready rows. Logging should include the webhook ID and dedupe key to trace a delivery across retries.\n\nWhen comparing delayed message queues and cron sweeps, delayed queues offer convenience through built-in retry and visibility settings managed by the broker. However, they also introduce operational dependencies such as retention and ordering rules. In contrast, a cron sweep over a due-time table provides greater inspectability, allowing operators to query late rows, replay events, or change leases without relying on broker-specific consoles. The trade-off is the added latency from polling.\n\nPer-event timers are the simplest to code but lack durability, making them suitable only for single-process utilities where missing a follow-up is not critical. They are not ideal for scenarios requiring auditability, frequent deployments, or multiple replicas receiving the same webhook.\n\nTo handle failures gracefully, treat the worker as a control loop that discovers ready work, admits it based on the downstream limit, executes it idempotently, and records the next state. Implement a semaphore around the carrier call to control concurrency. A drain loop can manage the worker, releasing permits as calls complete and leaving remaining rows in the ready state. Monitor metrics such as age at execution, queue age, retry counts, and retries-to-completions ratio to ensure the system is running smoothly and to prevent overload scenarios.",
  "summary": "Webhook Follow-Up Scheduling: Delayed Messages vs Per-Event Timers Explained Short answer: for a logistics webhook that must run about an hour later, put a durable due time in a queue-backed table and let a bounded worker claim it; use a cron sweep as the recovery path, not one timer per event. This keeps latency visible while a rate-limited pool drains at a controlled cost. Imagine a carrier…",
  "key_points": [
    "Store webhook event details in a durable FollowUp table with runAt timestamp",
    "Use poller with FOR UPDATE SKIP LOCKED to claim ready rows without blocking transactions",
    "Compare delayed queues and cron sweeps for trade-offs between convenience and inspectability"
  ],
  "editors_take": "Choosing between delayed queues and database-driven cron sweeps forces developers to trade the operational convenience of message brokers for the superior inspectability and control of a transactional polling system.",
  "illustration": null,
  "coverage": {
    "outlets": 1,
    "also_reported_by": []
  },
  "ai_generated": true,
  "disclaimer": "Summaries, key points and the editor’s take are written by software from other outlets’ reporting and may contain errors — always check the linked original."
}