stackwitness

Blog

When the cron is late and the host still answers

Cloudflare's 9 September 2026 Workers Cron Triggers incident left HTTP paths answering while scheduled jobs could miss or delay. How to separate a 200 from proof the job ran.

The Worker still returns 200. The marketing site loads. Last night's backup was supposed to run at 02:00 UTC. The Cron Trigger Events table has no row after 19:17. Is Cloudflare down? That question is too coarse. You need two clocks: the request path and the scheduler.

A recent case: Workers Cron Triggers, 9 September 2026

On 9 September 2026 at 19:17 UTC, Cloudflare opened a minor incident on the Workers component. The first update said Cron Triggers may not execute or may be delayed, and that updates to Cron Triggers may take some time to take effect. The Workers component moved from operational to degraded performance. At 19:18 UTC they marked the issue identified, with a fix being implemented. As of 10 September 2026 the incident was still open. Cloudflare's own page is incident sjs8s0q2x4hw.

Independent aggregators tracked the same window. IsDown's Cloudflare Workers history listed the incident as ongoing from 19:22 UTC. isinternetup.com's 10 September digest still had it open, next to a separate WARP geolocation issue. We do not invent whether any particular customer's scheduled handler missed a tick. The vendor named the failure mode: miss or delay, plus slow schedule updates.

What an operator of that scheduler actually checks

This shape is not new. In June 2026 a public Cloudflare community report described Cron Triggers going silent after a single Internal Error at 14:10:38 UTC. Last success on a */5 trigger was 14:05:38 UTC. After that, zero invocations of any kind, while the same Worker's HTTP handler still ran its usual API calls and writes. Cloudflare's MVP confirmed it as a platform scheduler issue and said it was fixed. That thread is Cron Triggers completely stopped firing after a single Internal Error. The September incident is a separate event. The check is the same.

Open the Worker in the Cloudflare dashboard, Settings, Trigger Events, View events. Cron Events keeps the last 100 invocations. Write down the last timestamp and put it next to 19:17 UTC. A 200 on the HTTP route does not add a row to that table.

Why the 200 fools people

A Cron Trigger is not an HTTP request. scheduled() is a different invocation path from fetch(). The public hostname answering is the request path. Treating them as one health check is how a nightly snapshot, a digest email, or a reconciliation job goes missing while uptime still looks clean.

On 10 September 2026 at 14:35 UTC, the StackWitness Cloudflare truth page showed host reachability as reachable and vendor self-report as degraded. That split is the two columns doing their job. Reachable means the host answered a probe. It is not a reading of whether scheduled() fired. See /status/cloudflare, and the index at /status.

Copy you can adapt

The weak version, which could be pasted onto any incident:

We are aware Cloudflare is experiencing intermittent issues. Some scheduled tasks may be delayed. All other systems remain operational. We apologize for any inconvenience.

That paragraph costs the restore point. On-call sees the Worker 200, files it under vendor noise, and does not open Cron Trigger Events. At 02:00 UTC the backup does not run. At 08:00 UTC the digest does not send. Tomorrow's rollback lands on a snapshot that is a day old, and nobody can say when the gap started.

The version that names the scheduler:

As of 19:17 UTC Cloudflare reports Workers Cron Triggers may not execute or may be delayed. Our HTTP Worker paths are answering. We are checking Cron Trigger Events for backup-worker (cron 0 2 * * *) and digest-worker (cron 0 8 * * *). We will not treat last night's jobs as done until we see an invocation after 19:17 UTC. We will not change cron expressions during this window and assume they took effect.

A reader who was not on the bridge can check that against Cloudflare's incident and against the last row in Cron Trigger Events. The weak paragraph cannot be checked, so it cannot be trusted an hour later.

What not to do

Operator checklist

  1. Name the scheduled job and its cron expression (0 2 * * * backup, not only "Cloudflare").
  2. Read the vendor incident body, not only the top badge. This one named Cron Triggers, not the request path.
  3. Open Cron Trigger Events for that Worker. Write down the last invocation time.
  4. If the last invocation is before the incident start, treat the job as not done. Run it by HTTP if that path is safe, or say the snapshot is stale.
  5. Keep HTTP health and scheduler health on separate lines in the customer update.

StackWitness measures host reachability and reads vendor self-reports so teams can attribute faster. A reachable host is still an outage for anyone whose scheduled job did not run. Name the cron you lost.

We measure reachability and read vendor self-reports. We never invent calm green or issue a compliance verdict.

Start free See live dependency truth