Nothing was broken. We fixed it anyway.
August 9, 2026 · 6 min read
At 15:15 on a Saturday, an alert fired: a sync pair had gone silent. No successful sync in four hours and thirty-five minutes.
Inside those four hours and thirty-five minutes, the pair had completed 55 syncs. All 55 of them succeeded. Not one failed.
The next one finished nine-tenths of a second after the alarm went off.
The move we didn’t make
There is an obvious response here and we’d rather be honest that we considered it. The alert was wrong. The pair was fine. You silence that alert for that pair, you get on with your Saturday, and nothing bad happens today.
The reason we don’t do that is not diligence for its own sake. An alert that cries wolf isn’t a small problem, it’s a slow-acting one. Every false page teaches whoever is on call to trust the alerts slightly less, and that trust is the entire value of having them. The failure mode isn’t the noisy alert. It’s the real one, six months later, that gets waved through because the last four were nothing.
So we went and looked.
Two parts of the system, disagreeing
Here’s the pair as our operations view showed it. Active, one-way, an ICS feed mirroring into Google, forty-eight events — and last synced eight hours ago.
polling only
mirror target
And here’s the sync job log for the same pair, at the same moment. A poll, four minutes ago, completed, in a tenth of a second.
| When | Pair | Trigger | Status | Took |
|---|---|---|---|---|
| 4m ago | 3331e323 | poll | done | 0.1s |
Both of those were reading the same system. One of them was lying.
The fast path that skipped a write
Our sync engine has a shortcut, and it’s a good one. When it polls a calendar and the provider replies that nothing has changed since last time, there’s nothing to copy. The engine stops early rather than doing pointless work.
The timestamp recording “this pair last synced” was written at the end of the full path. The shortcut returned before reaching it.
So the timestamp didn’t mean what its name said. It meant the last time an event actually moved. Three separate parts of the product read it as the last time a sync succeeded.
On a busy calendar those two are close enough together that nobody notices. On a quiet one they drift apart without limit — and the pairs most exposed were the ones fed by ICS subscriptions, which can’t receive push notifications and so poll constantly. Perfectly healthy, checking every five minutes, accumulating imaginary silence the whole time.
The bug behind the bug
This is where a minor alert stopped being minor.
That same timestamp is what we show you, on your dashboard, as “last synced.”
If your calendar had been quiet for eight hours, twocal told you it hadn’t synced in eight hours. It had. It had checked ninety-five times over those eight hours and correctly found nothing to do on every one of them. We were displaying possibly broken when the truth was working, nothing to report.
Nobody had complained about this. It’s precisely the kind of thing people don’t complain about — they notice the stale number, wonder whether the product is actually running, and quietly trust it a bit less. We’d never have found it from a support ticket. We found it because we chased an alert that was, itself, wrong.
Two fixes, not one
Make the timestamp honest. A check that finds nothing is a successful sync. We asked both providers, they said nothing changed, that’s a complete and successful pass. It gets recorded as one.
Stop the alert depending on it. This is the one that matters in five years.
A summary field is written by code, and any path through that code can skip the write — which is exactly what happened. A record of completed work is different: you can fail to write a record, but you can’t un-record a job that ran. So the alert now asks “has any sync job for this pair actually completed recently?” rather than trusting a cached number to have been maintained correctly.
The first fix repairs today’s symptom. The second means the next shortcut someone adds to the engine can’t quietly resurrect it.
The part where we broke our own fix on purpose
Both changes got tests. Then we did the thing we think separates a fix from a hope: we reverted each fix, one at a time, and confirmed its test failed.
A test that has never failed isn’t evidence. It’s decoration. If you don’t watch it go red, you don’t know whether it’s testing the thing you think it is — and a green suite full of tests that can’t fail is worse than no suite, because it’s reassuring.
Both went red on cue. Both went green again with the fixes restored.
And then we found a bug in the fix
Before shipping, we reviewed our own change. It had a bug in it.
The write we’d reached for to stamp the timestamp did something else as well: it also marked the pair’s status as healthy. And a pair sitting in an error state can reach that same shortcut, because we retry failed pairs on a timer.
So our fix would have cleared a genuine error — on a pass that never once touched the destination calendar. A pair broken on the destination side would have been reported as fine until the next real change re-broke it. That’s the same category of bug we’d sat down that afternoon to eliminate: reporting a state we hadn’t actually verified.
We caught it in review, split the write in two so that clearing an error stays the privilege of a sync that genuinely wrote something, and added a test for that too.
We’re including this because a story about rigour that omits the near-miss isn’t a story about rigour. The review caught it. That’s what the review is for.
Verifying it where it counts
Before deploying we recorded the pair’s timestamp: stuck at 07:20, eight and a half hours stale. One poll cycle after the fix went live:
polling only
mirror target
Nothing had changed on that calendar in the interim. No events moved. The timestamp advanced anyway — because a check that finds nothing is finally recorded as what it is.
Across every active pair we run, the alert’s new logic reported exactly zero as silent. The one false positive flipped. Nothing else moved.
What isn’t in that view
Those two panels are reproductions of our internal operations view, rebuilt here field for field. You may have noticed what they don’t contain: no name, no email address, no calendar title, no event, no meeting subject. An ID prefix, the providers involved, a direction, and a count.
Nothing was removed for publication. That is the entire view. When we’re debugging your sync, we work from anonymous identifiers and the shape of the problem. The content of your calendar isn’t something we need in order to fix it, so it isn’t something we put in front of ourselves.
Why bother, for this
This one happened to land at quarter past three on a Saturday afternoon. If it had landed at quarter past three in the morning, we’d have got up for it — that’s what an alert is, and an alert you’d ignore at 3am isn’t one. Which is exactly why a false one costs so much: we spend the same attention on it, and it spends down the credibility of the next.
No customer was affected in a way they’d have noticed this week. The whole thing cost an afternoon.
That’s roughly the point. The alerts you take seriously while they’re small are the reason you can trust them when they’re not. And in this case the small alert was a thread that led somewhere real — a number we’d been showing customers for months that didn’t mean what it said.
We publish our actual reliability numbers on the reliability dashboard, including the agreement rate between calendars rather than a green light that only proves our health check responded. This is the same instinct, applied inward: an alert should be as honest as the dashboard, and both should be as honest as the system.
If you want the longer argument for why silence is the failure mode that matters, we wrote that one up too: the webhook never arrived, and that’s still our problem.
Tired of sync that drops events?
twocal does one thing — keeps your calendars in sync, reliably. 14 days free, no credit card.