Spurlock Studios
Contact
Share LinkedIn X
A small text-file card with no glyphs. Thesis: CRON WEBHOOK PICK TRIGGER MATCHES.

Pick the trigger by how you will notice it dying — not by which demo looks faster. Webhooks win when the source can push and you can detect a dead subscription. Schedules win when freshness can wait and you need a heartbeat you control. Many production paths need both: a webhook for speed and a reconciliation cron that catches what the push missed.

This sits under the Production n8n handbook. Trigger choice is reliability design, not a preference for “real-time” branding. After 500+ automations, the expensive mistake is treating poll vs push as a taste question.

The short answer

  • Webhook (push) when the vendor supports events, latency has a cost, and you monitor subscription health.
  • Schedule / cron / polling when the API is pull-only, batch is fine, or you want a run you can prove happened.
  • Both fail silently in different ways — design detection for the mode you chose.
  • Hybrid is normal: webhook for the hot path, hourly or daily cron to reconcile gaps.
  • Vendor retry is not a constant. Stripe retries for days. GitHub does not retry. Zapier polling intervals are plan-dependent.

When should you poll vs push?

Poll when you must ask. Push when the source will tell you. That is the whole decision, plus the failure mode you can actually detect.

QuestionPush (webhook)Poll (cron / schedule)
Who initiates?Vendor POSTs to your URLYou GET/list on a timer
LatencySeconds, if delivery worksYour interval, plus query time
Proof of lifeTraffic, or a synthetic pingA run record at a known time
Typical missSubscription dead, URL rotated, HMAC wrongInterval too coarse, watermark skip, empty success
Cost shapeExecution per eventTick cost even when nothing changed
CompletenessWhatever the vendor deliveredWhatever your query returned

Use this order:

  1. Does the vendor document webhooks or an event API? If no, you poll. Stop pretending.
  2. If yes, can you verify the signature and respond fast enough for that vendor’s timeout? If no, fix that before you subscribe — see webhook security.
  3. What is the maximum lag the business will accept? If it is tighter than a honest poll, you need push, or you need to rename the SLA.
  4. What does silence look like? Zero POSTs, or a missed cron, or a green zero-row query?
  5. Is a reconciliation job in v1? On a revenue path, “later” means you accepted silent gaps.

If two rows conflict, ship webhook for intake and add a reconciliation schedule before you declare done.

When is real-time actually required?

Real-time is required when delay creates irreversible cost. “We like seeing it appear instantly in Slack” is not that.

PathDelay that hurtsPrefer
Lead routing while a human is on the phoneMinutesPush, plus a short reconcile
Fraud / access revokeSeconds to minutesPush; poll is a backstop only
Inventory or booking holdMinutesPush if the vendor has it
Payment confirmation that unlocks fulfillmentMinutesPush, plus a List-events reconcile
Nightly finance exportHoursSchedule
CRM hygiene / tag cleanupHours to a daySchedule
Slack “nice to know”WhateverSchedule is enough

Decision list:

  1. If this is late by X minutes, what breaks — money, access, or ego?
  2. If ego, pick a schedule you can explain.
  3. If money or access, require a documented event API or admit the lag.
  4. If the vendor offers only polling on Zapier or Make, buying a tighter interval is still sampling. Plan for gaps.

A five-minute schedule is often enough and easier to reason about than a webhook nobody is watching.

What does a webhook miss that a cron will catch?

A webhook only knows what arrived. It does not know what the source still holds.

GapWhy push misses itWhat the cron does
Subscription deleted or disabledZero deliveries; your dashboard looks fineLists source records and upserts the missing ones
URL rotated / test URL left in the vendorEvents go to a listener that is not productionSame list/upsert; also surfaces the count mismatch
Vendor gave up retryingStripe stops after its window; GitHub never startedPulls by updated_at or event id
Created and edited before you were subscribedMost event APIs are not a full history feedBackfill from a watermark
Filtered event typesYou subscribed to created and needed updatedQuery is wider than the subscription
HMAC / auth rejectVendor retries, then drops youCron never needed that POST

n8n’s Webhook node is a listener: test URL while you click Listen, production URL after you publish. Point a vendor at the test URL and the integration dies when the editor session ends. A cron does not care which URL you fat-fingered last Tuesday.

Stripe tells you to return a 2xx before slow side effects, then process the event — and to pull undelivered events when the endpoint was down. That pull is a poll. The vendors that take webhooks seriously still assume you will reconcile.

When does polling waste money and still miss events?

Polling costs show up as ticks, not as drama.

MeterWhat you pay forMiss it still has
Zapier tasksActions when a poll finds work (rules are plan-specific)Create-then-delete between polls
Make operations / check runsScheduled asks, including empty onesSame gap; plus queue caps on scheduled webhooks
n8n executionsEvery Schedule tick you allow to run the graphEmpty success if the query is wrong
Vendor rate-limit budget“Anything new?” loops429s that look like “the CRM is down”

Miss modes a faster poll does not fix:

  • Item created and deleted between ticks
  • Pagination that skips page two forever
  • Clock skew / updated_after filters that skip edits
  • Plan interval coarser than the SLA you promised sales
  • First page only, because someone hardcoded limit=50

Prefer webhooks when the vendor has them. Prefer schedules when the business accepts the cadence. Do not poll every minute “to be safe” without measuring cost and rate limits — that fight belongs in API rate limits in n8n.

Checklist before you tighten an interval:

  • Written max lag from the business owner, not from the tool default
  • Watermark (cursor, updated_at, or last id) stored outside the run
  • Pagination explicit; last page proven
  • Empty-success streak alert for this source
  • Daily full reconcile if the window can skip
  • Rate-limit headroom measured at the new cadence

Faster empty polls fail faster. They do not become a webhook.

How do silent failures differ by trigger?

Webhooks fail by absence of traffic. Schedules fail by absence of a run or by empty success. One Slack channel for “any error” catches neither.

TriggerSilent failureWhat operators seeDetection
WebhookSubscription deleted, URL rotated, vendor disabled eventsZero executions; dashboards look “fine”Expect N events/day or a synthetic ping
WebhookReceiver up, HMAC or auth wrongVendor retries, then gives upAlert on 4xx rate at the edge
WebhookTest URL in productionWorks in the editor, dies afterVendor delivery log vs n8n Executions
ScheduleWorkflow unpublished or cron mis-setNothing runs; no errorDead-man: alert if no success in 2× interval
ScheduleRuns green, query wrongEmpty success foreverItems processed > 0 over a window, or a reconcile count
Poll (Zapier / Make)Interval too slow / filter wrong“Missing” records blamed on the CRMDual-count source vs destination daily

n8n will not start a published Schedule until the workflow is published — their Schedule Trigger docs say so in a callout people skip. Unpublished is not “paused with a heartbeat.” It is off.

Make’s webhook docs add another silence: a webhook not attached to a scenario for more than five days is deactivated and returns 410 Gone. The vendor may still think the URL is live.

Do not share one pager-duty for “workflow error.” Split “no traffic” from “no run” from “run with zero rows.”

How do vendors retry — or refuse to?

“We have a webhook” is not a reliability class. Read the retry paragraph for that vendor.

VendorRetry on failed deliveryTimeout you must beatWhat you still poll for
StripeLive: up to three days, exponential backoff. Sandbox: three retries over a few hoursFast 2xx before slow workUndelivered / missed events via List Events
GitHubDoes not automatically redeliver10 seconds or it is a failureFailed deliveries (3-day UI/API window) plus your own reconcile
n8n as receiverYou choose Respond Immediately vs when the last node finishesWhatever the sender allowsYour own dead-subscription monitor
Make as receiverDefault 200 Accepted when queued; 400 if the queue is full; 429 over rate300 requests / 10 secondsQueue depth; inactive-hook 410

Stripe also regenerates Stripe-Signature on each retry. A replay window that keys only on the raw body without the event id will treat a retry as new. GitHub’s X-GitHub-Delivery is the id you store.

Stripe’s manual catch-up is not infinite: Dashboard Resend works for 15 days; stripe events resend via the CLI works for 30 days (same webhook page). After that you are on List Events plus your own datastore. GitHub’s UI/API redelivery window is 3 days. Miss that window and the cron is the only copy.

n8n Respond modes, from the Webhook node:

Respond settingWhat the sender getsUse when
ImmediatelyWorkflow got startedVendor timeout is tight (GitHub’s 10s)
When Last Node FinishesLast node’s payloadTiny graphs; you can finish inside the timeout
Using ‘Respond to Webhook’ NodeWhatever that node returnsYou need a custom 2xx early, then keep working
StreamingChunked bodyChat-style endpoints — not CRM writes

Payload cap is 16MB (N8N_PAYLOAD_SIZE_MAX if you self-host). A “webhook plus file” that exceeds it looks like the vendor is down. It is not. The body never entered the workflow.

Procedure when a vendor is “flaky”:

  1. Read their retry + timeout page. Do not guess from Stripe’s behavior.
  2. In n8n, set Respond to Immediately (or a Respond to Webhook node early) so GitHub’s 10-second clock is not waiting on a CRM write.
  3. Apply the side effect after the 2xx, with an idempotency key.
  4. Add a list/reconcile job for the window their retry does not cover.
  5. If they publish no retry at all, the reconcile job is the product.

A webhook without a documented retry is a best-effort push. Price the cron accordingly.

When do you ship webhook plus a reconciliation cron?

When money, access, or a booked human depends on completeness. That is most lead and order paths we ship.

LayerOwns
WebhookLatency and happy-path volume
CronCompleteness and catch-up
Idempotency keySafe overlap when both fire
HeartbeatProof the webhook path is alive
Diff reportProof the cron is doing work, not sleeping

Build order:

  1. Webhook workflow handles the event quickly, responds early, verifies the signature, writes with a stable key.
  2. Reconciliation schedule (hourly or daily) lists source records updated since the last watermark and upserts anything missing in the destination.
  3. Diff report posts to ops when the cron creates or repairs rows — so you learn webhook gaps instead of ignoring them.
  4. Shared validators so both paths reject the same bad shapes.
CadenceUse whenDo not use when
Every 15–60 minutesLead or order completeness during business hoursThe list API cannot page cheaply
DailyLow volume, or overnight catch-upSales promised “instant” with no push
Weekly full snapshotAudit / financeYou are using it as the only path

Hybrid costs one extra workflow. It buys sleep. If step 3 never fires a repair, either the webhook is healthy or the cron query is as blind as the webhook. Dual-count source vs destination before you celebrate.

What if the vendor has no webhooks?

Then you poll or schedule — honestly. Do not market a 15-minute Watch module as real-time.

Make’s own module types split this cleanly: Watch modules poll on the scenario schedule; instant modules are webhooks. If the app has no instant trigger, you are on a schedule whether the UI feels fancy or not. Their trigger-module guidance also assumes a date or numeric id you can watermark. No id, no safe poll.

  • Document the maximum acceptable lag with the business owner
  • Set poll/schedule interval inside that lag (not “as fast as the plan allows”)
  • Store a watermark (cursor, updated_at, or last id)
  • Handle pagination explicitly
  • Alert on zero-item success streaks that are abnormal for that source
  • Add a daily full reconcile if the poll window can skip
  • Rename the SLA in the runbook so sales cannot quote “instant”

n8n pattern that works: Schedule Trigger plus an HTTP Request (or app node) keyed on the watermark. That beats a webhook fantasy on a vendor that only lists records.

If the list API cannot sort descending, you will eventually miss the head of the pile. Make’s trigger docs warn that ascending order on a large collection cannot reach the latest records. Believe them. Change the query or change the vendor.

Watermark procedure we actually ship:

  1. Persist last_seen_at or last_seen_id in a store the next run can read — not in the execution log.
  2. Query updated_at >= last_seen_at (or id > last_seen_id) with an overlap of one interval to absorb clock skew.
  3. Page until empty. Do not stop at page one.
  4. Upsert by source id. Advance the watermark only after the last successful page.
  5. If a run fails mid-page, leave the watermark where it was. Re-processing overlap is cheaper than a silent skip.
WatermarkWorks whenBreaks when
updated_atThe API stamps editsCreates with a later created_at but stale updated_at
Monotonic idInsert-only streamsIds that recycle or arrive out of order
event.id cursorThe vendor lists eventsThe list is not complete (filtered types)
“Unread” / “since last run with no store”NeverHumans and other Zaps move the cursor

How often should you poll?

Start from business lag, not from tool defaults.

  1. Ask: “If this is late by X minutes, what breaks?”
  2. Set interval ≤ X / 2 when the API and the bill allow.
  3. Cap interval by rate limits and billable poll cost.
  4. Prefer fewer, richer batch jobs over chatty empty polls.
  5. Revisit after you have a week of missed-event rate, not after the first demo.
Max acceptable lagStarting intervalNotes
5 minutesYou probably need pushA 2-minute poll still has create-delete holes
15–30 minutes10–15 minutesCommon CRM Watch default; write it down
1–4 hours30–60 minutesBatch windows; watch rate limits
DailyNightly + on-demand buttonFinance, reporting, cleanup

In n8n, changing a Schedule interval does nothing until you unpublish and publish again. n8n’s common issues page is explicit: the new cadence starts from publish time. Change “every 1 hour at :00” to “every 2 hours” at 11:30 and the next run is 13:30, not noon. Operators call that “cron is broken.” It is not. You moved the epoch.

Cron variables evaluate at publish too. Edit the variable later and the schedule stays stale until you republish.

How do Zapier and Make meter polling vs instant?

Do not compare invoices until you compare failure modes. Then read the meter, because the meter changes how people pick a bad trigger.

Zapier’s How Zap triggers work page (verify your workspace — plans change) publishes polling intervals by plan:

Zapier plan (as documented there)Polling interval
Free15 minutes
Professional2 minutes
Team1 minute
Enterprise1 minute

Instant triggers are webhooks. Zapier does not poll those. You cannot flip a polling trigger to instant; the app’s API decides. Flood protection can hold a burst of poll results for review. Empty polls are not the same cost as n8n executions — Zapier meters tasks when the Zap runs work. Complexity and vendor rate limits remain even when a given empty check is not a task.

Make:

BehaviorWhat to remember
Polling WatchRuns on the scenario schedule; empty = a check run in History
Instant webhookDefault: run immediately, in parallel
Scheduled webhookQueue, then drain on the schedule
Default Maximum number of results2 — an hourly schedule with a growing queue drains two items an hour
Queue full400 Queue is full; inbound over 300 / 10s is 429

If you “made it a webhook” on Make and then scheduled the scenario, you built a queue. That is a valid pattern. It is not instant. Raise Maximum number of results or you will debug “missing events” that are sitting in the queue.

n8n meters executions. A Schedule that always runs the HTTP node costs a run every tick, including “nothing new.” Build the cheap-exit in the graph or accept the tick cost.

Upgrading a Zapier plan only for faster polls is sometimes rational. Rebuilding on a push-capable rail is sometimes cheaper over a year. Do the math on your volume, not on a blog’s.

How do you detect a dead webhook subscription?

A webhook that has been quiet for three days is not “stable.” It is unproven.

SignalHealthyDead or dying
Events / day vs baselineInside the bandZero during the business window
Vendor delivery log2xx4xx/5xx, or no attempts
n8n ExecutionsProduction URL, published workflowOnly test-URL runs, or nothing
Synthetic / canaryWeekly hit landsCanary missing; subscription gone in the vendor UI
Make hookAttached to an active scenario410 after five idle days

Checklist after go-live:

  • Baseline: expected events/day (even a rough band)
  • Alert if count = 0 for N hours during the business window
  • Synthetic event weekly in staging, or a canary record in prod
  • Log vendor delivery failures if the platform exposes them
  • On credential or URL change, re-verify the subscription in the vendor UI
  • Document who can re-create the webhook without guessing
  • Confirm the vendor is on the production URL, not the test URL
  • If GitHub: a scheduled job that lists failed deliveries and redelivers — they will not do it for you

Signature failures belong in webhook security. A 401/403 storm is a dead subscription with extra steps: the vendor is talking, then they stop.

Can n8n schedules pile up or fire at the wrong hour?

Yes. Overlap and timezone are the two schedule bugs that look like “n8n is random.”

If a schedule fires while the previous run still holds work, you can overlap writes unless you:

  • Set workflow concurrency / queue settings for your hosting mode
  • Make the job idempotent
  • Use a lock row or run token in your backend
  • Prefer “skip if running” where you have it

Overlapping crons that both “catch up” the same window are a classic duplicate-send source. Design for overlap. Do not assume serial perfection.

Timezone, from n8n’s Schedule docs and common issues:

LayerWho wins
Workflow timezoneIf set, the Schedule uses it
Instance timezoneFallback if the workflow has none
Self-hosted defaultAmerica/New_York unless you set GENERIC_TIMEZONE
n8n Cloud defaultDetected at signup, else GMT

Wrong-hour checklist:

  • Workflow timezone set on purpose, not inherited by accident
  • Self-hosted GENERIC_TIMEZONE matches the runbook (set the timezone)
  • Cron expression validated on crontab guru after dropping the optional seconds column
  • Day-of-month 30 or 31 accepted as “will not fire in February”
  • Interval change republished; next fire computed from publish time
  • DST: America/New_York springs forward — a 2:30 AM job can vanish

n8n cron can use six fields (seconds optional). Copy-pasting a five-field Unix cron into a six-field box shifts every column. That is how a daily 9:00 becomes “every 9 seconds” in a war room.

When is email or IMAP a bad trigger?

Email-as-trigger looks flexible and fails dirty. Use it for notify paths. For money or CRM truth, prefer API webhooks or scheduled API pulls with a schema contract.

ProblemWhy it hurts
HTML vs plain variantsOne vendor footer change breaks extraction
Duplicate delivers / threadingHarder idempotency than an event id
Latency and mailbox authOAuth expiry looks like “no mail”
Untrusted contentAutomation now executes whoever can send to that inbox
No watermark“Unread” is not a cursor; humans mark things read

Decision list:

  1. Is the message body your schema? If yes, stop. Use an API.
  2. Is the side effect reversible? If no, stop.
  3. Can a stranger’s email fire the workflow? If yes, you built an open webhook with worse auth.
  4. If you still need mail, treat it as a human queue: notify, do not write the CRM from the MIME.

IMAP polling is still polling. It has every poll miss mode, plus a mailbox. That is not a third trigger type. It is the worst one.

Trigger choice worksheet

Print this. Fill it before you add the node.

  1. Does the vendor document webhooks or events?
  2. Max acceptable lag, in minutes, signed by the business owner?
  3. What does silence look like for this trigger?
  4. Who gets the heartbeat alert, and in which window?
  5. Is a reconciliation cron in scope for v1?
  6. Idempotency key defined — event id, or source id + verb?
  7. Vendor retry + timeout read and pasted into the runbook?
  8. Production URL (not test) confirmed in the vendor UI?
  9. Timezone named (America/New_York or other), not “server default”?
  10. Dual-count query written (source count vs destination count)?

If (5) is “later” on a revenue path, you are accepting silent gaps. If (7) is blank, you are treating Stripe, GitHub, and a random SaaS as the same product.

Lane page for the rest of the operating system: automation.

FAQ

What if the vendor has no webhooks?

Use a schedule or poll with an explicit lag SLA, a watermark, pagination, and a reconcile job. Do not market it as real-time. Document the maximum delay the business accepted, and rename the runbook so nobody quotes “instant” from a Watch module.

How often should I poll?

Set the interval from business lag and rate limits, not from the fastest plan toggle. Start coarser, measure missed-event rate, then tighten. Faster polls without watermarks just fail faster, and they still miss create-then-delete gaps between ticks.

How do Zapier polling intervals affect cost?

Intervals are plan-dependent per Zapier’s trigger docs — Free is documented at 15 minutes, paid tiers tighter; verify your workspace. Tighter polls can detect sooner but do not remove reconciliation, and billable actions still meter when work runs. Instant triggers avoid poll cadence when the app supports them.

How do I detect a dead webhook subscription?

Alert on unexpected zero traffic, run a periodic synthetic event, and re-check the vendor subscription after any URL or credential change. Error workflows alone will not fire if no delivery attempt reaches you. On Make, an unattached hook can go 410 after five days.

Can schedule triggers pile up in n8n?

Yes when a previous execution is still running. Use concurrency controls, idempotency, and locks so overlapping ticks cannot double-apply. Assume overlap will happen under load, and treat a timezone miss as a separate bug from pile-up.

When is email/IMAP a bad trigger?

When the message body is your schema and the side effect is irreversible. Prefer API events or scheduled pulls for CRM and finance; keep mail for notifications and human-in-the-loop queues. Unread state is not a watermark.

CTA

Choose the trigger you can prove is alive — then add the other as a safety net when money moves.

Read the handbook, then use automation or book the audit.

FAQ

What questions does this article answer?

What if the vendor has no webhooks?
Use a schedule or poll with an explicit lag SLA, a watermark, pagination, and a reconcile job. Do not market it as real-time. Document the maximum delay the business accepted, and rename the runbook so nobody quotes "instant" from a Watch module.
How often should I poll?
Set the interval from business lag and rate limits, not from the fastest plan toggle. Start coarser, measure missed-event rate, then tighten. Faster polls without watermarks just fail faster, and they still miss create-then-delete gaps between ticks.
How do Zapier polling intervals affect cost?
Intervals are plan-dependent per Zapier's trigger docs — Free is documented at 15 minutes, paid tiers tighter; verify your workspace. Tighter polls can detect sooner but do not remove reconciliation, and billable actions still meter when work runs. Instant triggers avoid poll cadence when the app supports them.
How do I detect a dead webhook subscription?
Alert on unexpected zero traffic, run a periodic synthetic event, and re-check the vendor subscription after any URL or credential change. Error workflows alone will not fire if no delivery attempt reaches you. On Make, an unattached hook can go `410` after five days.
Can schedule triggers pile up in n8n?
Yes when a previous execution is still running. Use concurrency controls, idempotency, and locks so overlapping ticks cannot double-apply. Assume overlap will happen under load, and treat a timezone miss as a separate bug from pile-up.
When is email/IMAP a bad trigger?
When the message body is your schema and the side effect is irreversible. Prefer API events or scheduled pulls for CRM and finance; keep mail for notifications and human-in-the-loop queues. Unread state is not a watermark.
Sources

Last reviewed

More from this lane

Automation

All →
Book the audit