A ghost lock blocked every cron trigger for 6 hours after a Korean ad-network API took 45 seconds to respond — 15 seconds past the Workers wall clock limit.

The Workers runtime doesn't queue a second invocation and wait for the first to finish. It fires the next cron tick regardless. So when my D1 write job occasionally crept past 30 seconds, two instances ran simultaneously, both inserting aggregated impression rows faster than my UNIQUE constraint could reject them. The 3am wake-up call was D1_ERROR: UNIQUE constraint failed: impressions.event_id.

The obvious fix is a distributed lock with a TTL — so even if the Worker dies mid-run without releasing, the lock eventually clears itself. I tried KV first because it's simpler. The code looks correct:

const existing = await env.KV.get(lockKey);

if (existing) return; // skip this tick