When Good Logging Takes Down Your Whole System

backlit40341 pts0 comments

When Good Logging Takes Down Your Whole System

The Forensic Engineer

SubscribeSign in

When Good Logging Takes Down Your Whole System<br>Sometimes doing it "right" isn't enough.

Manpreet Kaur Sasan<br>Jul 08, 2026

Share

Ever been so responsible it backfired?<br>Bluesky’s engineering team knows the feeling. They did the “right” thing - logged every error, exactly like you’re taught to - and it took their whole system down for a weekend.<br>Thanks for reading The Forensic Engineer ! Subscribe for free to receive new posts and support my work.

Subscribe

A blocking syscall, a thread explosion, and a sharp bit of thinking under pressure. Let’s get into it.<br>The Byte

Observability, monitoring, logging - they’re meant to catch failures, not cause them. Or so I thought.<br>Turns out they can take your whole system down too.<br>In April 2026, Bluesky quietly shipped a new internal service. Nothing alarming about it - low traffic, nothing flagged in review.<br>But one endpoint was missing a limit that every other endpoint in the system had. For a week, that went unnoticed.<br>Then, on Saturday, April 4, alerts started trickling in. The team’s first instinct was a network issue - reasonable, but wrong. The system limped along through the weekend.<br>By Monday, April 6, it gave way completely. Half their users were affected for eight hours.<br>The twist: the system’s own error logging was the actual cause of the collapse. Every failed operation was being logged, exactly as good practice says it should be.<br>But in Go, writing a log entry is a “blocking” action - the program stops everything else until that one line is fully written. Normally, a tiny pause nobody notices.<br>But thousands of these pauses, every second, add up faster than a system can clear them. The runtime kept compensating, and the compensation made things worse. A system built to catch failures ended up feeding one.<br>The Breakdown

Here’s why it happened, step by step:<br>The Spark - One endpoint had no limit on concurrent requests. A burst of 20,000 came in at once, and the system tried to open 20,000 connections simultaneously.

The Lock-Up - Closed connections don’t free up instantly; they stay reserved briefly before reuse. With that many opening at once, the system ran out of available connections. New attempts failed outright.

The Block - Every failure got logged. Writing a log line uses a blocking write syscall (true in Go, common in many languages) - it pauses the program until done. Thousands of failures meant thousands of tiny pauses, stacking up fast.

The Overload - With so many tasks stuck waiting, the runtime spun up new, heavier real threads so other work wouldn’t be stuck behind them. This holds true in almost any modern language - lightweight tasks run cheaply on top of a few real threads, until one blocks, and the system compensates by creating more. Do that for thousands of tasks in seconds, and a lean handful of threads becomes an overcrowded mess.

The Freeze - Those extra threads spiked memory pressure. Cleanup had to pause everything just to catch up.

The Loop - The moment things unfroze, every stalled task woke up at once, rushed the same exhausted connections, and triggered the same failure again. A fire the system kept re-lighting.

The Workaround - To buy time, engineers stopped routing every connection through one address. They spread connections across hundreds instead. Slots multiplied, and the cycle broke - for now.

Each step was the correct behavior of one layer, triggering the correct behavior of the next - until the sum of “correct” became a collapse.<br>The team didn’t do the wrong thing by logging failures. What was missing was rigor: a cap on how much could run at once, and separation between the logging path and the system it watched.

That same gap - assuming something is safe at any volume - shows up everywhere: input validation, retries, rate limits, anything on the unhappy path nobody stress-tests.<br>It matters even more in AI-augmented systems, where we’re logging every model call and treating that pipeline as free.<br>Bluesky’s outage wasn’t really about logging. It was about an assumption nobody checked. Somewhere in your codebase, something’s making the same one. Might be worth finding it before production does.<br>Sources: Bluesky’s postmortem on pckt.blog, with additional analysis from Lorin Hochstein on Surfing Complexity.<br>Thanks for reading The Forensic Engineer ! Subscribe for free to receive new posts and support my work.

Subscribe

Share

Discussion about this post<br>CommentsRestacks

Ready for more?

Subscribe

© 2026 Manpreet Kaur Sasan · Privacy ∙ Terms ∙ Collection notice<br>Start your SubstackGet the app<br>Substack is the home for great culture

This site requires JavaScript to run correctly. Please turn on JavaScript or unblock scripts

system logging down whole subscribe connections

Related Articles