<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Sonia Bobrik</title>
    <description>The latest articles on DEV Community by Sonia Bobrik (@sonia_bobrik_1939cdddd79d).</description>
    <link>https://dev.to/sonia_bobrik_1939cdddd79d</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3423281%2Fb9547be6-14b6-48f6-8a94-9de77fde6ca0.jpg</url>
      <title>DEV Community: Sonia Bobrik</title>
      <link>https://dev.to/sonia_bobrik_1939cdddd79d</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/sonia_bobrik_1939cdddd79d"/>
    <language>en</language>
    <item>
      <title>On December 6, Wall Street Moves Midnight to 8 p.m.</title>
      <dc:creator>Sonia Bobrik</dc:creator>
      <pubDate>Sun, 11 Oct 2026 13:56:29 +0000</pubDate>
      <link>https://dev.to/sonia_bobrik_1939cdddd79d/on-december-6-wall-street-moves-midnight-to-8-pm-oe4</link>
      <guid>https://dev.to/sonia_bobrik_1939cdddd79d/on-december-6-wall-street-moves-midnight-to-8-pm-oe4</guid>
      <description>&lt;p&gt;For as long as anyone has built software around U.S. stocks, the market has handed engineers a quiet gift every weeknight: eight hours between the end of post-market trading at 8 p.m. Eastern and the 4 a.m. pre-market open, when the exchanges went dark and nobody minded a restart. Investor relations teams are already rethinking release schedules now that &lt;a href="https://massivelyop.com/author/Corporate_News_Is_Losing_Its_Overnight_Buffer/" rel="noopener noreferrer"&gt;corporate news is losing its overnight buffer&lt;/a&gt;, yet the first people to feel the change will be the engineers whose batch jobs, deploys and reconciliations live in that same gap. On Sunday, December 6, 2026, U.S. equities are scheduled to start trading 23 hours a day, five days a week, and the single hour that survives comes with a new answer to an old question: when does a day end?&lt;/p&gt;

&lt;h2&gt;
  
  
  The Trade Date Now Starts the Evening Before
&lt;/h2&gt;

&lt;p&gt;Under the FINRA definitions scheduled to take effect that day, a trade date stops lining up with a calendar day. It opens at 8:00 p.m. Eastern and closes at 8:00 p.m. the following day, so anything executed after 8 p.m. belongs to tomorrow, even when tomorrow is a Saturday or a holiday. The examples in &lt;a href="https://www.nasdaq.com/docs/post-trade-23/5-faq" rel="noopener noreferrer"&gt;Nasdaq's post-trade FAQ&lt;/a&gt; show what that looks like on the wire. A fill at 9:30 p.m. on Monday, December 7 goes out with Tuesday's date in FIX tag 75 (TradeDate) and settles on Wednesday, while tag 60 (TransactTime) keeps the real moment of execution. Nasdaq will even compute tag 336 (TradingSessionID) from that timestamp so clearing can tell overnight trades apart.&lt;/p&gt;

&lt;p&gt;Put differently, the trade date on a confirmation and the date on a New York wall clock will disagree for four hours every night, by design. The vocabulary disagrees too: Nasdaq's rule filing calls the new hours the Night Session, NYSE Arca and Cboe call theirs the Overnight Trading Session, and Nasdaq markets the whole program as Global Trading Hours. Normalize session names at the edge of your system, the same way you normalize currency codes.&lt;/p&gt;

&lt;h2&gt;
  
  
  The UTC Shortcut That Only Works in Summer
&lt;/h2&gt;

&lt;p&gt;If your code derives a trade date from a timestamp, two shortcuts will pass review and then fail. Taking the calendar date in Eastern time is wrong for everything between 8 p.m. and midnight. Taking the date in UTC, which is exactly what you get by slicing the date off a FIX TransactTime, is sneakier. During daylight saving time, 8 p.m. EDT is precisely midnight UTC, so &lt;strong&gt;the UTC date matches the new trade date from March to November&lt;/strong&gt; and every test built from summer data passes. Clocks fall back on November 1. From then on, 8 p.m. Eastern is 1 a.m. UTC, and every post-market trade between 7 and 8 p.m. gets stamped with tomorrow's date. The overnight session launches five weeks into standard time.&lt;/p&gt;

&lt;p&gt;The fix is boring, which is the point:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;date&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;timedelta&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;zoneinfo&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;ZoneInfo&lt;/span&gt;

&lt;span class="n"&gt;ET&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;ZoneInfo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;America/New_York&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;ROLLOVER&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;time&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;# 8:00 p.m. Eastern opens the next trade date
&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;trade_date&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;executed_at&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;date&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;executed_at&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tzinfo&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="nc"&gt;ValueError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;refusing to guess the zone of a naive timestamp&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;local&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;executed_at&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;astimezone&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ET&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;local&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;time&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="n"&gt;ROLLOVER&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;local&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;date&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nf"&gt;timedelta&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;days&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;local&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;date&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="n"&gt;UTC&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;ZoneInfo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;UTC&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;monday_930pm_est&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;datetime&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2026&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tzinfo&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;UTC&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;monday_730pm_est&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;datetime&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2026&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tzinfo&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;UTC&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;# already Tuesday in UTC
&lt;/span&gt;&lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="nf"&gt;trade_date&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;monday_930pm_est&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="nf"&gt;date&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2026&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;# trades as Tuesday
&lt;/span&gt;&lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="nf"&gt;trade_date&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;monday_730pm_est&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="nf"&gt;date&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2026&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;# still Monday's trade
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice what the function does not need: a holiday calendar. Under the new definitions the trade date is plain clock arithmetic. The calendar comes back for settlement, since T+1 still skips weekends and market holidays.&lt;/p&gt;

&lt;h2&gt;
  
  
  Your Maintenance Window Is Now One Hour Long
&lt;/h2&gt;

&lt;p&gt;The SIPs that publish consolidated quotes and trades, along with the FINRA/Nasdaq trade reporting facilities, will run from 9 p.m. Sunday to 8 p.m. Friday. The only weekday gap is the hour between 8 and 9 p.m., Monday through Thursday, reserved for processing and the switch to the next trade date. Apart from the odd market holiday, the stretch from Friday evening to Sunday evening becomes the only window long enough for a schema migration or a nervous upgrade.&lt;/p&gt;

&lt;p&gt;The hour itself is stricter than the old evening. Firms using Nasdaq's post-trade risk service currently have until 8:20 p.m. to act on held trades. That grace period disappears, and the clearing firm's default, allow or inhibit, applies to every held trade at 8:00 p.m. sharp.&lt;/p&gt;

&lt;p&gt;Then there is the job somebody schedules this month. In October, 8:15 p.m. Eastern is 00:15 UTC, so &lt;code&gt;15 0 * * *&lt;/code&gt; looks like it lands safely inside the pause. After November 1 it fires at 7:15 p.m., in the middle of live post-market trading. Shift it to &lt;code&gt;15 1 * * *&lt;/code&gt; for winter and, on March 14, 2027, it starts firing at 9:15 p.m., a quarter hour into the night session. The day-of-week field drifts as well, because Tuesday at 00:15 UTC is still Monday evening in New York. On Kubernetes, set &lt;code&gt;.spec.timeZone&lt;/code&gt; to &lt;code&gt;America/New_York&lt;/code&gt; (the field has been stable since v1.27) and write the schedule in Eastern time. Don't smuggle &lt;code&gt;CRON_TZ=&lt;/code&gt; into the schedule string instead; the API server rejects it with a validation error.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Night a Venue Cancels Your Fills
&lt;/h2&gt;

&lt;p&gt;Overnight trading in U.S. stocks isn't new, and its biggest stress test went badly. On August 5, 2024, as Japan's Nikkei had its worst day since 1987, Blue Ocean, which Bloomberg described as the largest dedicated overnight venue in the U.S., buckled under the volume, halted and canceled every trade executed between 1:45 and 3:06 a.m. Eastern. Brokers that relied on it, Robinhood and a string of Korean firms among them, had to unwind trades their customers had already seen as filled. Korean financial authorities later counted roughly 630 billion won, about $435 million, in canceled transactions across some 90,000 accounts.&lt;/p&gt;

&lt;p&gt;Exchanges bring sturdier plumbing to the night session, but the night still behaves differently from the day, and every difference is a place where a state machine can go wrong. Here is what I would check before December 6:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Derive trade dates from execution time, never from arrival time.&lt;/strong&gt; Unreported, corrected or canceled trades from one session can arrive as prior-day messages once the next night session opens at 9 p.m., after the new trade date has already begun.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Make every fill reversible.&lt;/strong&gt; Keep executions in an append-only ledger and model busts as compensating entries, so a 3 a.m. cancellation becomes an event you replay instead of a row someone deletes by hand.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Expect a mass cancel at 4 a.m.&lt;/strong&gt; Nasdaq cancels night-session orders that are still open when the session ends, and it won't accept market orders overnight. An order manager that only tracks the cancels it sent will show customers ghost orders.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Teach your halt handling a new code.&lt;/strong&gt; Stocks facing splits, large dividends, mergers, spin-offs or symbol changes will be halted before the night session and, for Nasdaq listings, reopened through an 8 a.m. halt cross. Nasdaq tags these halts M1, and a halt by the listing market applies on every exchange.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Keep "last trade" and "last sale" apart.&lt;/strong&gt; Trades outside 9:30 to 4 carry the Form T sale condition, so they add to consolidated volume but can't update the official last sale. A chart that plots one while a risk check reads the other will disagree all night.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Check which feed your vendor consumes.&lt;/strong&gt; Nasdaq plans to publish night-session activity on a separate market-data feed, with new Plus products covering the whole day.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Book a test slot.&lt;/strong&gt; Industry test sessions are set for October 16 and 30, November 6 and 20, and December 4, and Cboe plans to let firms trade production test symbols in its overnight session from November 9.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Somebody's Morning Is Your Overnight
&lt;/h2&gt;

&lt;p&gt;The hours that feel like the dead of night in New York are a workday elsewhere. As &lt;a href="https://www.euronews.com/business/2026/08/18/nasdaq-confirms-23-hour-trading-from-december-with-new-overnight-session" rel="noopener noreferrer"&gt;Euronews noted in its report on Nasdaq's 23-hour schedule&lt;/a&gt;, the 9 p.m. to 4 a.m. Eastern session runs from 3 a.m. to 10 a.m. Central European Time. In Seoul the same window falls between 11 a.m. and 6 p.m. Those are the people who will be trading, and they hint at who should be on call: a follow-the-sun rotation beats paging a New York engineer at 2 a.m. to interpret a halt message.&lt;/p&gt;

&lt;p&gt;None of this calls for heroics. Most of it is work teams postponed because the old schedule forgave it: a timestamp stored without a zone, a cron line written in UTC, a ledger that deletes rows, a halt handler that only knows the codes it has already seen. The overnight session takes that forgiveness away. Replay a Sunday night and a Monday evening through staging now, while 8 p.m. is still a quiet hour, so that the first Tuesday that begins on a Monday evening is one you planned for.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Your Fire Escape Runs Through the Fire</title>
      <dc:creator>Sonia Bobrik</dc:creator>
      <pubDate>Sun, 11 Oct 2026 13:53:34 +0000</pubDate>
      <link>https://dev.to/sonia_bobrik_1939cdddd79d/your-fire-escape-runs-through-the-fire-36di</link>
      <guid>https://dev.to/sonia_bobrik_1939cdddd79d/your-fire-escape-runs-through-the-fire-36di</guid>
      <description>&lt;p&gt;For two hours on February 28, 2017, Amazon could not mark S3 as down on its own health dashboard, because the dashboard's admin console depended on S3. Every postmortem contains two stories, and that detail belongs to the second one. The first story explains what broke, and it gets the headlines. The second explains how the team got back, and it keeps revealing that the tools needed to end an outage were standing on top of the thing that failed. A recent essay on &lt;a href="https://4fund.com/eadzac?/When-Invisible-Systems-Break/" rel="noopener noreferrer"&gt;dependency blindness and the quiet ways invisible systems break&lt;/a&gt; flags the habit behind it as a warning sign: recovery plans that "depend more on memory and intuition than on clear system design." The biggest outages of the past decade keep proving that warning right.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Status Page That Lived on the Patient
&lt;/h2&gt;

&lt;p&gt;The S3 story is worth retelling in full. At 9:37 a.m. Pacific, an engineer on the S3 team, following an established playbook, ran a command meant to remove a small number of servers from a subsystem used by the billing process. One input was entered incorrectly. A far larger set of servers disappeared, including the ones behind two subsystems that the rest of S3 in us-east-1 relied on: the index, which manages the metadata and location of every object in the region, and placement, which allocates storage for new ones. Both needed a full restart.&lt;/p&gt;

&lt;p&gt;That is where the first invisible system surfaced. As &lt;a href="https://aws.amazon.com/message/41926/" rel="noopener noreferrer"&gt;Amazon's own summary of the S3 disruption&lt;/a&gt; admits, the company had "not completely restarted the index subsystem or the placement subsystem in our larger regions for many years." S3 had grown enormously in the meantime, so restarting those systems and running the safety checks that validate their metadata took longer than expected. The index was fully back at 1:18 p.m. and placement at 1:54 p.m. Meanwhile, the service statuses on that dashboard couldn't be updated until 11:37 a.m., so the largest cloud provider in the world reported on its own outage through Twitter and banner text.&lt;/p&gt;

&lt;p&gt;The typo started that morning, but it didn't decide its shape. A cold-start path nobody had walked at current scale decided how long it lasted, and a status page living on the patient decided how little customers could see while it did.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Safety Feature That Hid the Building
&lt;/h2&gt;

&lt;p&gt;Facebook's outage on October 4, 2021 followed the same script at a higher volume. During routine maintenance, a command meant to assess the availability of global backbone capacity took down every connection in the backbone instead. An audit tool existed to block exactly that kind of command, and a bug in it let the command through.&lt;/p&gt;

&lt;p&gt;Then a safety mechanism finished the job. Facebook's DNS servers are built to stop advertising their BGP routes when they can't reach the data centers, which is normally a sensible way for an unhealthy location to step aside. With the backbone gone, all of them stepped aside at once, and Facebook, Instagram and WhatsApp vanished from the internet for roughly six hours.&lt;/p&gt;

&lt;p&gt;Meta's &lt;a href="https://engineering.fb.com/2021/10/05/networking-traffic/outage-details/" rel="noopener noreferrer"&gt;engineering write-up of the outage&lt;/a&gt; is unusually candid about the way back. Engineers could not reach the data centers "through our normal means because their networks were down," and "the total loss of DNS broke many of the internal tools we'd normally use to investigate and resolve outages like this." So people were sent on site, into facilities designed to be hard to get into, full of hardware and routers designed to be hard to modify even with physical access. Every lock that keeps an attacker out is also a lock your own engineers will have to open on the worst day of the year.&lt;/p&gt;

&lt;p&gt;The same post holds the hopeful half of the story. Once the network was back, Meta couldn't simply switch everything on, because its data centers had dropped tens of megawatts of power draw, and reversing that suddenly could put "everything from electrical systems to caches at risk." It restored traffic in stages and credited the "storm" drills it had been running for a long time, exercises that take a service, a data center or an entire region offline on purpose. The way back had been rehearsed, and it showed.&lt;/p&gt;

&lt;h2&gt;
  
  
  Fixing the Bug Is the Short Part
&lt;/h2&gt;

&lt;p&gt;Newer incidents let you measure the gap between repairing a cause and recovering a system. On October 19 and 20, 2025, a latent race condition in DynamoDB's automated DNS management left the service's regional endpoint in us-east-1 with an empty DNS record. The trouble started at 11:48 p.m. Pacific, and all DNS information was restored by 2:25 a.m. The event itself didn't end until 2:20 that afternoon.&lt;/p&gt;

&lt;p&gt;Those remaining twelve hours were recovery, as everything built on DynamoDB tried to come back, and one of the first systems in line was a component few customers had heard of. EC2's DropletWorkflow Manager holds a lease on every physical server, or droplet, that hosts instances, and its checks on those leases depend on DynamoDB. While DynamoDB was unreachable, the leases expired one by one, and a droplet without a lease can't receive new instances. When DynamoDB returned at 2:25 a.m., the manager began re-establishing leases across the entire EC2 fleet, the work took so long that it timed out and was queued again, and the system fell into what AWS calls "congestive collapse." The summary also contains a sentence worth reading twice: the situation "had no established operational recovery procedure."&lt;/p&gt;

&lt;p&gt;Google Cloud hit the same wall in June 2025. A policy change with unintended blank fields sent its Service Control binaries into a global crash loop, and an emergency switch that disabled the failing code path was fully rolled out within 40 minutes. In us-central1, though, full recovery took up to about two hours and forty minutes, because the restarting tasks stampeded the Spanner table they depend on. Google's report says plainly that Service Control "did not have the appropriate randomized exponential backoff." GitHub met a version of the same problem on August 17, 2026, when errors in some Copilot services set off a client-side retry loop that added traffic during recovery, and the team had to tame it before it could safely restore traffic.&lt;/p&gt;

&lt;p&gt;The purest example arrived in May 2026. Coinbase ran its exchange matching engine as a five-node Raft cluster inside an AWS cluster placement group, a feature that packs instances close together within one availability zone for low latency. After several chillers failed in one AWS data hall, a thermal shutdown followed, and when AWS terminated instances in that group, three of the five nodes went down and the cluster lost quorum. According to Coinbase's postmortem, getting it back took a new node group outside the impaired placement group and "an emergency code change shipped during the incident to remove a startup assumption that all five cluster nodes were resolvable." The startup path assumed a healthy cluster. It was code that only matters after a disaster, built on a premise that only holds when there isn't one.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why the Way Back Rots
&lt;/h2&gt;

&lt;p&gt;None of these teams was careless. They ran into a property of recovery code that has nothing to do with skill: it is the least-executed code you own. The happy path runs millions of times a day, so a broken assumption in it gets caught within minutes. The cold start, the failover script, the break-glass account and the status-page login may run once every few years, and the system keeps changing underneath them the whole time.&lt;/p&gt;

&lt;p&gt;That change comes from three directions, and each one looks like progress. Growth changes the physics, so a restart that took minutes at launch takes hours at today's scale, as S3 discovered. Consolidation changes the topology, because putting chat, docs, dashboards, paging and deploys behind one identity provider in one cloud is efficient right up until that provider or that cloud is what's down. Hardening changes the locks, so the controls that keep attackers away from production also slow down your own responders. Each decision is reasonable on its own, and none of them shows up on a dashboard, because dashboards measure a running system, not the path for bringing a dead one back. &lt;strong&gt;Recovery paths rarely break in one dramatic moment. They drift, one sensible decision at a time, until they route straight through the failure they were built to escape.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Write a Bill of Materials for the Way Back
&lt;/h2&gt;

&lt;p&gt;We already know how to make hidden dependencies visible. Teams generate software bills of materials so nobody has to guess what a build contains. The way back deserves the same treatment: a short document listing everything a recovery needs, built by asking one question of every item, "what does this need in order to work, and could that be down at the same time?" Start with these:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The status page.&lt;/strong&gt; If it shares a cloud account, a DNS provider or a login with your product, assume it goes dark with your product, the way AWS's dashboard did in 2017.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Access.&lt;/strong&gt; Can someone with authority reach production when SSO, the VPN or the office network is down? Break-glass credentials belong outside the identity provider they exist to bypass, and they need testing on a schedule, because an untested break-glass account is only a rumor.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Runbooks.&lt;/strong&gt; If they live in a wiki behind the same login and network as production, keep an exported copy somewhere that shares neither.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Communication.&lt;/strong&gt; Pick an incident channel that depends on neither your own infrastructure nor your main identity provider, and make sure everyone on call knows where it is before they need it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cold starts.&lt;/strong&gt; Record when each critical system last started from zero, not one instance at a time, and how long it took. If the honest answer is "never," every recovery estimate you have is a guess.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Startup assumptions.&lt;/strong&gt; Read your boot and init code for anything that expects a full cluster, a reachable config service or a fixed peer count. Those are Coinbase's five resolvable nodes waiting to happen.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Retries.&lt;/strong&gt; Every client and worker that retries should back off exponentially with jitter, or your recovery will arrive as a stampede.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Expect at least one loop on the first pass, such as a secrets vault hosted on the cluster it holds the keys for, or a deploy pipeline that needs the service it is supposed to redeploy. Finding it on paper is cheap. Finding it during an incident is how a short outage turns into a long one.&lt;/p&gt;

&lt;h2&gt;
  
  
  Rehearse Without Your Tools
&lt;/h2&gt;

&lt;p&gt;Chaos engineering usually asks whether a system survives a failure. The postmortems above raise a narrower and more uncomfortable question: can your team recover when its own tools are part of the failure? Meta's storm drills point toward the answer. For your next game day, take something away from the responders instead of from production. Declare the identity provider down, move the team off its usual chat workspace, or require one service to come up cold in a fresh environment with nothing cached. Then listen for the moment someone says, "wait, how do we..." Each of those moments is an invisible dependency surfacing on a quiet afternoon instead of in the middle of the night with customers watching. Add it to the bill of materials, fix the worst one, and run the drill again next quarter.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Fire Code Principle
&lt;/h2&gt;

&lt;p&gt;Buildings learned this long before software did, mostly from fires that taught it the hard way. Fire codes insist that exits keep working after everything else in the building has failed. Exit signs and emergency lighting carry their own backup power, stairwells are enclosed and separated from the rest of the structure, and everyone knows not to take the elevator. Underneath all of it sits one rule: the way out must not depend on the systems that are on fire.&lt;/p&gt;

&lt;p&gt;Software has no fire marshal, so the inspection falls to us. Walk your exit route while the building is quiet, and make sure it doesn't run through the fire.&lt;/p&gt;

</description>
      <category>architecture</category>
      <category>aws</category>
      <category>devops</category>
      <category>sre</category>
    </item>
    <item>
      <title>Hype Is Technical Debt, and Crypto Always Collects</title>
      <dc:creator>Sonia Bobrik</dc:creator>
      <pubDate>Sun, 11 Oct 2026 13:52:56 +0000</pubDate>
      <link>https://dev.to/sonia_bobrik_1939cdddd79d/hype-is-technical-debt-and-crypto-always-collects-o1i</link>
      <guid>https://dev.to/sonia_bobrik_1939cdddd79d/hype-is-technical-debt-and-crypto-always-collects-o1i</guid>
      <description>&lt;p&gt;Every long-lived codebase has a file nobody wants to open, usually the one with a "TODO: clean up after launch" comment older than half the team. Most crypto projects have a marketing twin of that file: the pinned launch-week thread promising mainnet by Q3, a tier-one exchange listing and partnerships that "can't be announced yet." That thread kept coming back to me while I listened to Sofia and Nika of the crypto marketing agency Techwaves share &lt;a href="https://goodpods.com/podcasts/the-seasonal-tokens-podcast-crypto-investing-not-gambling-214904/episode-44-expert-perspectives-on-the-current-state-of-the-crypto-mark-29802639" rel="noopener noreferrer"&gt;their expert view of the current state of the crypto market&lt;/a&gt; with host Polar Mil on The Seasonal Tokens Podcast. Along the way they get into the mistakes crypto projects make most often and how people who market crypto for a living think about hype.&lt;/p&gt;

&lt;p&gt;The episode aired in May 2023, half a year after FTX imploded, and the problems it digs into have not aged a day. The guests come at them from the marketing desk. This post comes at them from the repo, because from where developers sit, hype behaves exactly like debt, and we already know how debt ends.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Metaphor Was Born in Finance Software
&lt;/h2&gt;

&lt;p&gt;The term "technical debt" comes from Ward Cunningham's 1992 OOPSLA experience report on WyCash, a system for managing cash portfolios. It is fitting that the idea maps so cleanly back onto markets. Cunningham's argument was simple: shipping code you know is not quite right is a loan. Borrowing a little lets you move faster, provided you repay it soon by reworking the code. The trouble starts when nobody ever does.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.mckinsey.com/capabilities/tech-and-ai/our-insights/tech-debt-reclaiming-tech-equity" rel="noopener noreferrer"&gt;McKinsey's research on tech debt&lt;/a&gt; splits the concept into the two parts of any loan. The principal is the work you will eventually have to do anyway. The interest is the complexity tax every project pays in the meantime. The numbers are sobering: in a survey of 50 CIOs, respondents reported that 10 to 20 percent of the technology budget meant for new products was being diverted to tech-debt issues, and they put the debt itself at 20 to 40 percent of the value of their entire technology estate.&lt;/p&gt;

&lt;p&gt;Now run the same split on a token launch. The principal of hype debt is the gap between what you have announced and what you have shipped. The interest is everything that gap costs while it stays open: a support channel that asks "wen mainnet" every morning, engineers pulled off the roadmap to write reassurance threads, and every new holder who bought the promise rather than the product. Technical debt charges interest in engineering hours. Hype debt charges it in trust, the one asset no protocol can mint.&lt;/p&gt;

&lt;h2&gt;
  
  
  Not All Hype Debt Is Reckless
&lt;/h2&gt;

&lt;p&gt;Martin Fowler's technical debt quadrant sorts debt along two axes, deliberate versus inadvertent and reckless versus prudent, and it transfers to marketing almost one to one. &lt;strong&gt;Prudent and deliberate&lt;/strong&gt; is announcing a testnet window to recruit early node operators, knowing you will have to hit it or explain in public why you missed. &lt;strong&gt;Reckless and deliberate&lt;/strong&gt; is promising exchange listings you do not control and hinting at price targets you have no business discussing. &lt;strong&gt;Reckless and inadvertent&lt;/strong&gt; is paying an influencer without knowing what disclosure the law expects. &lt;strong&gt;Prudent and inadvertent&lt;/strong&gt; is discovering after launch that your messaging attracted traders instead of users, and rewriting it before the mismatch hardens into your reputation.&lt;/p&gt;

&lt;p&gt;McKinsey makes a point about software that applies here too: the goal is not zero debt. A well-placed announcement can be worth what it costs. The goal is to know which quadrant you are borrowing from, and to write the loan down.&lt;/p&gt;

&lt;h2&gt;
  
  
  How the Bill Arrives
&lt;/h2&gt;

&lt;p&gt;Crypto collects hype debt through three channels, and none of them sends a polite reminder first.&lt;/p&gt;

&lt;p&gt;The first is the market. A liquidity crunch is the moment the market stops accepting IOUs. On October 10 and 11, 2025, just days after Bitcoin set a record above $126,000, a sudden tariff shock set off more than $19 billion in liquidations, the largest such event the asset class has ever recorded. Major coins dropped by double digits, and plenty of smaller tokens fell much further. When leverage unwinds, a token is worth roughly what it actually does, and narrative premium is the first thing sold.&lt;/p&gt;

&lt;p&gt;The second is your own community. Unpaid hype debt turns your Discord into an incident channel and your roadmap into a list of apologies. Every hour your engineers spend on damage control is interest in its purest form.&lt;/p&gt;

&lt;p&gt;The third is the law. When the SEC &lt;a href="https://www.sec.gov/newsroom/press-releases/2022-183" rel="noopener noreferrer"&gt;charged Kim Kardashian for touting EthereumMax's token on Instagram&lt;/a&gt;, the case came down to a single post she had been paid $250,000 to publish without disclosing the payment. She agreed to pay $1.26 million, without admitting or denying the findings, and not to promote crypto asset securities for three years. The post even carried an #ad hashtag, which shows how little a hashtag covers: the regulator's position was that the nature, source and amount of compensation all had to be disclosed. Enforcement priorities shift with every administration, but the anti-touting provision of US securities law dates back to 1933. If your growth plan includes paid promoters, their disclosures are your problem too.&lt;/p&gt;

&lt;h2&gt;
  
  
  Ship Evidence, Not Adjectives
&lt;/h2&gt;

&lt;p&gt;Builders hold one big advantage in the hype economy: in crypto, almost any claim can be made checkable. Contracts can be verified on a block explorer, benchmarks can live in the repo as scripts anyone can rerun, audits can be pinned to the exact commit they reviewed, and usage can be read straight from the chain. A project that markets with artifacts instead of adjectives pays down principal with every post.&lt;/p&gt;

&lt;p&gt;The most practical tool I know for this is a promise ledger: a public board, or even a pinned GitHub issue, where every external commitment gets a row with the date it was made, an owner, a status and a link to the evidence once it ships. Think of it as a bug tracker for marketing. Nobody gets to make a promise without adding a row, and the row stays visible until it is closed.&lt;/p&gt;

&lt;p&gt;Before any announcement goes out, run it through a short pre-flight check:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Every claim has an artifact.&lt;/strong&gt; A commit hash, a contract address, a testnet URL or a reproducible benchmark. If the evidence does not exist yet, the claim waits.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Dates come with their blockers.&lt;/strong&gt; "Mainnet in Q3" is a mood. "Mainnet once the bridge audit, currently in review, is complete" is a plan people can follow.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Updates talk about users, not price.&lt;/strong&gt; Describe what people can do now that they could not do last month, and leave the chart out of it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Paid promotion is disclosed in full.&lt;/strong&gt; Who paid, how much and for what, in writing, before anything goes live.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The changelog ships with the post.&lt;/strong&gt; If an update cannot link to release notes, it is not an update yet.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Read the Repo Before the Chart
&lt;/h2&gt;

&lt;p&gt;The podcast's own tagline is "crypto investing, not gambling," and hype debt is roughly where that line runs. A project carrying heavy hype debt asks you to bet on its ability to repay. A project that ships evidence asks you to inspect something real. Developers are unusually well equipped to tell the difference: compare a roadmap from a year ago with the commit history today, check whether the audited code matches what is actually deployed, and count how many public promises are still open. None of this predicts price. It does tell you whether you are investing in a product or underwriting a narrative.&lt;/p&gt;

&lt;h2&gt;
  
  
  Pay It Down Before the Market Does It for You
&lt;/h2&gt;

&lt;p&gt;Bear markets work like forced refactors. They strip out whatever was held together by momentum and keep whatever was actually built. The projects that make it to the next cycle are rarely the loudest ones from the last. They are the ones whose announcements read like release notes, whose promise ledgers stayed short, and whose developers spent the drawdown shipping instead of apologizing.&lt;/p&gt;

&lt;p&gt;So treat every public commitment the way you would treat a shortcut in code: take it on purpose, write it down and pay it back on schedule. And before you hit post, ask one question. Would you be comfortable seeing this tweet quoted in your postmortem?&lt;/p&gt;

</description>
      <category>crypto</category>
      <category>marketing</category>
      <category>startup</category>
    </item>
    <item>
      <title>Every Free Tier Is a Loan: Capital Discipline for Developers</title>
      <dc:creator>Sonia Bobrik</dc:creator>
      <pubDate>Sat, 10 Oct 2026 19:46:34 +0000</pubDate>
      <link>https://dev.to/sonia_bobrik_1939cdddd79d/every-free-tier-is-a-loan-capital-discipline-for-developers-57a9</link>
      <guid>https://dev.to/sonia_bobrik_1939cdddd79d/every-free-tier-is-a-loan-capital-discipline-for-developers-57a9</guid>
      <description>&lt;p&gt;For roughly a decade, the cheapest input in software was somebody else's money. Venture capital quietly paid for generous free tiers, "unlimited" flat-rate plans and permissively licensed infrastructure, and most of us built on top of all of it without ever reading the terms as terms. A sharp analysis of &lt;a href="https://ventsmagazine.co.uk/capital-discipline-is-becoming-the-decisive-advantage-in-business/" rel="noopener noreferrer"&gt;how capital discipline separates durable companies from fragile ones&lt;/a&gt; argues that markets now reward the businesses that can roll their obligations over at today's prices without tearing up the plan. Developers should take that personally, because our stacks are full of loans nobody remembers signing, and plenty of them are maturing right now.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Refinancing Wall Is Not Just a Bond-Market Problem
&lt;/h2&gt;

&lt;p&gt;In finance, a refinancing wall is what you hit when a big pile of cheap debt comes due at roughly the same time and has to be replaced with new debt at much higher rates. The OECD's &lt;a href="https://www.oecd.org/en/publications/global-debt-report-2026_e9d80efd-en.html" rel="noopener noreferrer"&gt;Global Debt Report 2026&lt;/a&gt; describes exactly that pressure: companies borrowed more from markets in 2025 than ever before in real terms, about $13.7 trillion, and because the debt maturing next is mostly low-cost paper issued before rates jumped, interest bills keep ratcheting up with every rollover.&lt;/p&gt;

&lt;p&gt;Your vendors live inside that report. A developer-tools company that raised at a 2021 valuation and subsidized growth with nearly free capital is now being asked by its own investors and lenders for margins, not just signups. That pressure doesn't stay on its balance sheet. It flows downstream, straight onto your pricing page.&lt;/p&gt;

&lt;p&gt;Here is the uncomfortable mapping. &lt;strong&gt;A free tier is a loan at a 0% teaser rate:&lt;/strong&gt; the vendor lends you service below cost in exchange for future lock-in. A flat-rate plan with fuzzy limits is an interest-only mortgage. A permissive license on a project controlled by a single venture-backed company is a variable-rate note whose terms the lender can rewrite. None of these are bad deals. They're just deals, and deals have maturity dates.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Wall Has Been Maturing in Public
&lt;/h2&gt;

&lt;p&gt;If this sounds abstract, scroll back through a few years of changelogs. Heroku retired its free dynos in late 2022. HashiCorp moved Terraform to a source-available license in 2023, and the community answered with the OpenTofu fork. In February 2024, AWS started charging $0.005 an hour for every public IPv4 address, roughly $44 a year for something that used to cost nothing, multiplied across every load balancer, NAT gateway and forgotten test instance. A few weeks later Redis dropped its BSD license, and within about a week the Linux Foundation had launched Valkey, a fork with the major cloud providers behind it. After Broadcom closed its VMware acquisition, perpetual licenses gave way to bundled subscriptions. AT&amp;amp;T publicly cited a projected 1,050% increase in its bill, and even the two-to-threefold uplift Gartner described as more common is the kind of number that rewrites a budget.&lt;/p&gt;

&lt;p&gt;The pattern isn't anecdotal. Vertice's SaaS inflation index put average year-over-year software price increases at roughly 12% in late 2025, about four times the US consumer inflation rate. Every event above was a rate reset. The teams that got hurt weren't the ones who used the cheap tier. They were the ones with no plan for the day it ended.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Biggest Teaser Rate in Your Stack Right Now
&lt;/h2&gt;

&lt;p&gt;For many developers in 2026, that teaser rate lives inside the editor. In June 2025, Cursor switched its $20 Pro plan from a fixed allowance of 500 requests to a usage pool billed at model API prices, and the backlash ended in a public apology and refunds. This spring GitHub made a calmer version of the same move. In the post announcing that &lt;a href="https://github.blog/news-insights/company-news/github-copilot-is-moving-to-usage-based-billing/" rel="noopener noreferrer"&gt;GitHub Copilot is moving to usage-based billing&lt;/a&gt;, the company's chief product officer acknowledged that a one-line question and an hours-long agent run had cost the user the same, that GitHub had been eating much of the rising inference bill, and that the old premium-request model could not continue. Since June 1, most Copilot usage draws down credits based on the tokens it actually consumes.&lt;/p&gt;

&lt;p&gt;Base plan prices didn't move, and code completions are still included. That is exactly what a polite refinancing looks like: the same monthly payment, new terms on everything that actually costs money.&lt;/p&gt;

&lt;p&gt;Now read that with a capital allocator's eyes. If your team's workflow depends on agents that run for an hour at a time, the price of that hour was never the price you were paying for it. A 2027 engineering budget that assumes today's AI spend is modeling a teaser rate as if it were fixed.&lt;/p&gt;

&lt;h2&gt;
  
  
  Read Your Stack Like a Credit Analyst
&lt;/h2&gt;

&lt;p&gt;Credit analysts don't ask whether a company is good. They ask what happens when its debt reprices. You can run the same review on your dependencies in an afternoon, and it starts with a plain spreadsheet: every service, license and tool that something important relies on, with five questions answered for each.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;What is the real coupon?&lt;/strong&gt; Price the dependency as if the subsidy vanished tomorrow: the self-hosted cost, a competitor's list price, or the raw API rate hiding behind the flat fee. The gap between that number and what you pay today is your exposure.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Who controls the covenant?&lt;/strong&gt; A project governed by a foundation with many corporate contributors behaves like a fixed-rate loan. A project where one company owns every copyright can be relicensed whenever its board needs a better margin.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;When is the likely maturity date?&lt;/strong&gt; Resets have tells: a funding round that's years old, a new CFO, an acquisition, layoffs, a "pricing update" banner, or a free tier that shrinks a little every quarter.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Is there a refinancing path?&lt;/strong&gt; A protocol-compatible fork, an open standard, or a second provider you could genuinely switch to. If the only alternative is a rewrite, you aren't diversified, you're hoping.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;How correlated is the exposure?&lt;/strong&gt; One vendor running your CI, your code review and your coding agents is a single counterparty. When it reprices, everything reprices at once.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Refinance Before You're Forced To
&lt;/h2&gt;

&lt;p&gt;The point isn't to avoid vendors. Self-hosting everything is just another way to overpay, in engineering hours instead of invoices. The point is to make sure no single reset can blow up a roadmap.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Put seams where the repricing risk is concentrated, not everywhere.&lt;/strong&gt; A thin internal interface in front of your model provider costs a few days and turns a price hike into a config change. Three layers of abstraction around your ORM "just in case" cost months and protect you from nothing. Prefer standards over products at the boundaries, too: SQL, S3-compatible storage, OCI images and OpenTelemetry are the fixed-rate mortgages of software. Teams that only used core Redis commands found Valkey close to a drop-in swap, while teams leaning on proprietary modules had a much harder conversation.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Rehearse the exit.&lt;/strong&gt; A migration path that has never run is a theory. Once a quarter, point your test suite at the alternative: the fork, the second model provider, the self-hosted build. A few minutes of CI time is a cheap insurance premium.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Meter your own usage before the vendor does.&lt;/strong&gt; Put token spend, egress and per-seat costs on the same dashboard as latency. When metered billing lands, you'll already know which workflows are cheap and which are quietly expensive.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why the Person With the Map Wins
&lt;/h2&gt;

&lt;p&gt;The capital discipline argument from the top of this post has a second half that's easy to skim past: credibility lowers the cost of capital, because lenders charge extra for uncertainty. Engineering budgets behave the same way. The developer who walks into planning with a one-page map of the stack's teaser rates (what each dependency costs today, what it would cost at market, when it's likely to reset, and what leaving would take) is doing capital allocation, whether or not anyone calls it that. That's the person who gets handed the next big architectural decision, because their numbers survive contact with finance.&lt;/p&gt;

&lt;p&gt;Cheap money built half of the modern toolchain. It isn't coming back, but the toolchain is still running, and it's still quietly accruing interest. The only real question is whether you find the reset date on your own calendar or on an invoice.&lt;/p&gt;

</description>
      <category>cloud</category>
      <category>infrastructure</category>
      <category>startup</category>
    </item>
    <item>
      <title>Money Moves in Seconds Now. Your Billing Code Is the Bottleneck.</title>
      <dc:creator>Sonia Bobrik</dc:creator>
      <pubDate>Sat, 10 Oct 2026 19:39:46 +0000</pubDate>
      <link>https://dev.to/sonia_bobrik_1939cdddd79d/money-moves-in-seconds-now-your-billing-code-is-the-bottleneck-60d</link>
      <guid>https://dev.to/sonia_bobrik_1939cdddd79d/money-moves-in-seconds-now-your-billing-code-is-the-bottleneck-60d</guid>
      <description>&lt;p&gt;A transfer sent over the Federal Reserve's instant payment rail lands in the recipient's account within seconds, even at 3 a.m. on a Sunday. The invoice behind that transfer may have needed the better part of two months to get there, crawling through a month-end batch job, a shared accounts-payable inbox, two approval queues and a reconciliation spreadsheet that someone updates on Fridays. That gap is exactly why the argument that &lt;a href="https://www.londondaily.news/why-cash-velocity-is-becoming-the-real-measure-of-business-strength/" rel="noopener noreferrer"&gt;cash velocity, not revenue, has become the real test of business strength&lt;/a&gt; deserves a developer's attention and not only a CFO's. How quickly earned money turns into money a company can actually spend is now decided less by banks and more by software, and a lot of that software is written by people like us.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Banks Stopped Being the Excuse
&lt;/h2&gt;

&lt;p&gt;For most of the history of business payments, slow money had an alibi. ACH moved in batches that typically settled a business day or two later, wires paused for weekends and holidays, and a paper check could spend a week traveling and clearing. Nobody outside a bank could do much about any of that, so engineering teams treated the payment timeline like the weather.&lt;/p&gt;

&lt;p&gt;That alibi has expired. On July 20, 2023, the Fed &lt;a href="https://www.federalreserve.gov/newsevents/pressreleases/other20230720a.htm" rel="noopener noreferrer"&gt;launched FedNow, its round-the-clock instant payments service&lt;/a&gt;, which lets banks and credit unions of any size move money for their customers at any hour, on any day of the year. Jerome Powell's launch statement even used our scenario as a selling point: a company getting immediate access to its funds when an invoice is paid. Europe went a step further and turned speed into an obligation. Under the Instant Payments Regulation, banks in the euro area have had to accept instant euro transfers since January 2025 and send them since October 2025, at a price no higher than a regular transfer and with a free check that the payee's name matches the account number. The &lt;a href="https://www.ecb.europa.eu/paym/retail/instant_payments/html/instant_payments_regulation.en.html" rel="noopener noreferrer"&gt;European Central Bank's guide to the Instant Payments Regulation&lt;/a&gt; lays out the staggered deadlines, which reach the EU countries outside the euro area in 2027. Add the UK's Faster Payments, India's UPI and Brazil's Pix, and instant transfers are an everyday habit for hundreds of millions of people.&lt;/p&gt;

&lt;p&gt;So the interbank leg, the part everyone used to blame, can now take seconds. What stays slow is everything that happens before someone presses "send," and everything that happens after the money lands but before anyone knows what it was for. Both of those are software.&lt;/p&gt;

&lt;h2&gt;
  
  
  Follow One Invoice and Watch Where the Days Go
&lt;/h2&gt;

&lt;p&gt;Pick an ordinary B2B invoice from last quarter and replay its life as a timeline. The client signed off on the work on the 3rd, but invoices come out of a month-end batch job, so the bill didn't exist until the 1st of the following month. It traveled as a PDF attached to an email, landed in a shared accounts-payable mailbox and waited for someone to key it into the customer's ERP. It bounced once because the purchase order number was missing. It waited a week for an approver who was on holiday. It was slotted into the customer's weekly payment run. When the money finally arrived, the reference field read something like "INV2231 2232 PART," and someone on your side lost a morning working out which invoices it covered and why it was short.&lt;/p&gt;

&lt;p&gt;Not one of those delays happened inside a payment network. Each lives in a system somebody designed: a cron schedule, an email template, an import script, a validation rule, a matching spreadsheet. The money itself was in motion for a few seconds. Everything around the money took seven weeks.&lt;/p&gt;

&lt;h2&gt;
  
  
  Payment Messages Finally Have Room to Explain Themselves
&lt;/h2&gt;

&lt;p&gt;The second shift is quieter, and it matters even more to anyone who writes integration code. For decades most payments carried only a few cramped lines of free text about their purpose, which is why matching money to invoices turned into a manual craft. That is changing. The Fed moved Fedwire, its wholesale wire system, to the ISO 20022 message standard in a single-day cutover on July 14, 2025, and Swift ended the period in which banks could still use legacy MT messages for cross-border payment instructions on November 22, 2025. FedNow and Europe's instant payment schemes were built on ISO 20022 from day one.&lt;/p&gt;

&lt;p&gt;The part developers should care about is structured remittance data. An ISO 20022 payment can reference specific invoices in fields software can parse, instead of a string a human has to decode. If your invoices carry a unique, machine-readable reference, and your payment links and bank instructions pass it through untouched, matching a payment to an invoice stops being detective work and becomes a database join. Finance teams call the result &lt;strong&gt;automated cash application&lt;/strong&gt;. Engineers can simply call it deleting a manual step.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Invoice Is Becoming an API Payload
&lt;/h2&gt;

&lt;p&gt;The document is changing as well. France's e-invoicing mandate went live on September 1, 2026: every VAT-registered business established there must now be able to receive electronic invoices through an approved platform, large and mid-sized companies must also issue them, and smaller firms join on the issuing side in September 2027. Germany has required businesses to accept e-invoices since January 2025, and the EU's VAT in the Digital Age package, adopted in March 2025, makes e-invoicing mandatory for cross-border B2B trade inside the EU from July 2030.&lt;/p&gt;

&lt;p&gt;A PDF is a picture of data. A structured invoice is the data itself, and that changes what the receiving side can automate: validate it on arrival, match it to a purchase order, route it to the right approver and schedule the payment without anyone retyping a line. Each of those steps used to be a queue measured in days. If you build billing, procurement or accounting software, this is the moment when "export to PDF" stops being a feature and starts being technical debt.&lt;/p&gt;

&lt;h2&gt;
  
  
  What to Build Before the Next Billing Cycle
&lt;/h2&gt;

&lt;p&gt;None of this needs a banking license. It needs someone to treat the path from "work accepted" to "cash applied" as a product surface rather than a back-office chore. These changes offer the best ratio of engineering effort to days saved:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Invoice on the event, not the calendar.&lt;/strong&gt; Generate the bill when a milestone is accepted or a usage period closes. A month-end batch can quietly add almost a month of dead time before the customer even sees a number.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Give every invoice a machine-matchable identity.&lt;/strong&gt; Use a unique reference that survives the trip through the payment message, or assign each customer a virtual account number, so incoming money identifies itself.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Put a pay-now path inside the invoice.&lt;/strong&gt; A payment link or bank instruction that works over instant rails removes the wait between "approved" and "paid." FedNow and The Clearing House's RTP network both support request-for-payment messages, so ask your bank or payment provider what it exposes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ingest bank data as events.&lt;/strong&gt; Pull intraday reports and payment notifications (camt.052 and camt.054 in ISO 20022 terms, or your provider's webhooks) instead of a once-a-day CSV, and apply cash automatically whenever the reference matches.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Validate before you send.&lt;/strong&gt; Block your own invoice if the purchase order number, tax ID or billing contact is missing. A bounce your code catches costs seconds; a bounce the customer's AP team catches can cost a week.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Make disputes loud.&lt;/strong&gt; A rejected or disputed invoice should open a ticket with an owner and a deadline instead of sitting unread in a shared inbox.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Find Your Slowest Stage With One Query
&lt;/h2&gt;

&lt;p&gt;Days sales outstanding tells you how long collection takes overall, but not which stage to fix. For that you need timestamps. If your billing system writes a row to an &lt;code&gt;invoice_events&lt;/code&gt; table each time an invoice changes state (&lt;code&gt;work_accepted&lt;/code&gt;, &lt;code&gt;invoice_sent&lt;/code&gt;, &lt;code&gt;invoice_approved&lt;/code&gt;, &lt;code&gt;payment_scheduled&lt;/code&gt;, &lt;code&gt;payment_received&lt;/code&gt;, &lt;code&gt;cash_applied&lt;/code&gt;), this PostgreSQL query shows how long invoices sit in each stage and what share of all waiting time each stage owns:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;WITH&lt;/span&gt; &lt;span class="n"&gt;steps&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="k"&gt;SELECT&lt;/span&gt;
    &lt;span class="n"&gt;invoice_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;stage&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;occurred_at&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;LEAD&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;occurred_at&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;OVER&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="k"&gt;PARTITION&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt; &lt;span class="n"&gt;invoice_id&lt;/span&gt; &lt;span class="k"&gt;ORDER&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt; &lt;span class="n"&gt;occurred_at&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;left_at&lt;/span&gt;
  &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;invoice_events&lt;/span&gt;
  &lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;occurred_at&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="n"&gt;now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;interval&lt;/span&gt; &lt;span class="s1"&gt;'120 days'&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;SELECT&lt;/span&gt;
  &lt;span class="n"&gt;stage&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="k"&gt;COUNT&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;invoices&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;ROUND&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;percentile_cont&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;WITHIN&lt;/span&gt; &lt;span class="k"&gt;GROUP&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="k"&gt;ORDER&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt; &lt;span class="k"&gt;EXTRACT&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;EPOCH&lt;/span&gt; &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;left_at&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;occurred_at&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;86400&lt;/span&gt;&lt;span class="p"&gt;)::&lt;/span&gt;&lt;span class="nb"&gt;numeric&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;median_days&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;ROUND&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;SUM&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;EXTRACT&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;EPOCH&lt;/span&gt; &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;left_at&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;occurred_at&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="k"&gt;SUM&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;SUM&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;EXTRACT&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;EPOCH&lt;/span&gt; &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;left_at&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;occurred_at&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt; &lt;span class="n"&gt;OVER&lt;/span&gt; &lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;pct_of_total_wait&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;steps&lt;/span&gt;
&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;left_at&lt;/span&gt; &lt;span class="k"&gt;IS&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;
&lt;span class="k"&gt;GROUP&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt; &lt;span class="n"&gt;stage&lt;/span&gt;
&lt;span class="k"&gt;ORDER&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt; &lt;span class="n"&gt;pct_of_total_wait&lt;/span&gt; &lt;span class="k"&gt;DESC&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each row describes the stage an invoice was sitting in and how long it stayed there before the next event, so &lt;code&gt;pct_of_total_wait&lt;/code&gt; is the column to sort your backlog by. When &lt;code&gt;invoice_sent&lt;/code&gt; dominates, the delay looks like the customer's fault, yet the cure is often on your side: a missing PO field, an invoice delivered to the wrong mailbox or a format their system can't ingest. When &lt;code&gt;payment_received&lt;/code&gt; is large, your own reconciliation is the bottleneck, and the machine-readable references described above are the fix.&lt;/p&gt;

&lt;h2&gt;
  
  
  Speed Is a Design Decision Now
&lt;/h2&gt;

&lt;p&gt;When money needed days to cross the banking system, cash velocity looked like something the banks controlled. Now that money can move in seconds, a seven-week gap between delivering value and being able to spend the proceeds is mostly the sum of small choices: one batch schedule, one PDF template, one manual matching rule at a time. Companies that close that gap fund their next hire, their next experiment and their next bad quarter with their own money instead of someone else's. And the people best equipped to close it are the ones who already spend their days finding the slowest stage in a system and engineering it away.&lt;/p&gt;

</description>
      <category>backend</category>
      <category>fintech</category>
      <category>softwaredevelopment</category>
    </item>
    <item>
      <title>The Ship in Your Dependency Graph</title>
      <dc:creator>Sonia Bobrik</dc:creator>
      <pubDate>Sat, 10 Oct 2026 19:38:01 +0000</pubDate>
      <link>https://dev.to/sonia_bobrik_1939cdddd79d/the-ship-in-your-dependency-graph-kj</link>
      <guid>https://dev.to/sonia_bobrik_1939cdddd79d/the-ship-in-your-dependency-graph-kj</guid>
      <description>&lt;p&gt;On March 14, 2024, four subsea cables off Côte d'Ivoire failed almost simultaneously, and Microsoft started warning customers in its South Africa North and South Africa West regions about rising latency and dropped packets. Nobody had pushed a bad config, and no certificate had expired. Some operators failed over automatically while others spent hours buying capacity on cables that still worked, but the broken glass itself had to wait for the &lt;a href="https://blessingorbit.com/sixty-old-ships-are-holding-up-the-internet/" rel="noopener noreferrer"&gt;small, aging fleet of repair ships that quietly keeps the internet running&lt;/a&gt;, and that wait is the one part of our stack almost nobody writes into a design doc. If your product crosses an ocean, there is a ship somewhere in your dependency graph, and it is worth knowing how that ship schedules its work.&lt;/p&gt;

&lt;h2&gt;
  
  
  Four Cables, One Failure Domain
&lt;/h2&gt;

&lt;p&gt;WACS, MainOne, SAT-3 and ACE look like four-way redundancy on a network diagram. On the seabed they were neighbors. MainOne's preliminary analysis ruled out human activity, given the depth of the fault, and pointed to movement of the seabed itself, which means a single geological event took out every "independent" path at once. Engineers meet this pattern constantly at smaller scale: two availability zones fed by one substation, two DNS providers managed through one registrar account, two "diverse" fiber routes squeezed through the same bridge. &lt;strong&gt;Redundancy is not a count of paths. It is a claim that their failures are uncorrelated&lt;/strong&gt;, and geography is extremely good at falsifying that claim.&lt;/p&gt;

&lt;p&gt;The seabed correlates failures in time, too. &lt;a href="https://www.nature.com/articles/s41467-022-31689-3" rel="noopener noreferrer"&gt;Research published in Nature Communications&lt;/a&gt; followed underwater avalanches of sand and mud, known as turbidity currents, down the Congo Canyon off West Africa. One flow in January 2020 ran for more than 1,130 kilometers, accelerating from about 5 to 8 meters per second, and snapped two seabed telecom cables, slowing the internet from Nigeria to South Africa. Those cables had gone roughly 18 years without such a break, and then they broke again in March 2020, April 2021 and January 2022. The trigger was not an earthquake but the biggest Congo River floods in decades, with the destructive flows arriving weeks to months after the flood peak, often at spring tides. Some cables even survived flows of similar speed that snapped their neighbors, most likely because erosion was patchy and concentrated around steep steps in the canyon floor. Read that with on-call eyes: failures arrive in bursts after an observable precursor, and small differences in placement decide which replica lives.&lt;/p&gt;

&lt;h2&gt;
  
  
  Mean Time to Repair Is a Queue
&lt;/h2&gt;

&lt;p&gt;Logical recovery happens in routers. Physical recovery happens on a ship, and ships are a scarce shared resource with a scheduler. In July 2026, &lt;a href="https://www.itu.int/en/mediacentre/Pages/PR-2026-07-10-Submarine-cable-resilience-report.aspx" rel="noopener noreferrer"&gt;the final report of an international advisory body on submarine cable resilience&lt;/a&gt;, set up by the ITU (the UN agency whose X.509 standard defines the certificates in your TLS stack) and the International Cable Protection Committee, put hard numbers on that scheduler. Between 2012 and 2024, the average time to begin a repair more than doubled, from under 20 days to over 50, even though the yearly number of repairs and of available ships stayed flat; permitting delays take most of the blame. About 70 vessels can technically fix a cable, yet only 20 to 25 are dedicated to repair work or on long-term charter, and a significant share were built in the 1980s or 1990s. Asia-Pacific and the North Atlantic each host roughly 40% of the active repair fleet, while Africa, the South Atlantic and the Pacific islands share about 13%. A fault in the North Atlantic is often handled within 3 to 5 days, while a comparable one off West Africa can take 12 to 18.&lt;/p&gt;

&lt;p&gt;Africa shows the sharpest version of this. The whole continent has one permanently stationed, dedicated repair ship, Orange Marine's Léon Thévenin, built in 1983 and based in Cape Town. In 2024 it left port on March 19 for the Côte d'Ivoire breaks, where it took SAT-3 while another vessel, CS Sovereign, was assigned the other three cables. It was back in Cape Town by April 25. On May 12, Seacom and EASSy broke off the KwaZulu-Natal coast, cutting all subsea capacity between South Africa and East Africa, and on May 14 the same ship sailed again. One server, two coasts, strictly serialized. Orange Marine has since ordered two new ships to replace it and a 1987-built vessel in Italy, with delivery planned for 2028 and 2029.&lt;/p&gt;

&lt;p&gt;If you have ever watched a worker pool saturate, you know the curve. In the textbook single-server queue, the average wait equals utilization divided by one minus utilization, measured in service times: at 50% busy a new job waits about one repair, and at 90% busy it waits nine. Cable repairs are long jobs, since every splice keeps the ship holding position for a day or more and needs a weather window to do it. That is why correlated faults hurt twice. They arrive together, and then they queue together.&lt;/p&gt;

&lt;h2&gt;
  
  
  What a Cut Looks Like From Your Side
&lt;/h2&gt;

&lt;p&gt;A cable cut rarely shows up as a red outage banner. It shows up as gray failure: health checks pass, error rates look tolerable, and users in one geography quietly have a terrible day. The physics explains why. Light in fiber covers roughly 200,000 km per second, so every extra 1,000 km of detour adds about 10 ms of round-trip time. A single TCP connection can move at most one window of data per round trip, so doubling the RTT roughly halves what that connection can push, before you even count congestion on the detour. NetBlocks' research director made exactly that point during the March 2024 outage: as networks route around damage, they can drain capacity that other countries depend on, so the first problem may be physical while the ones that follow are technical. Meanwhile your client timeouts, tuned to last month's p99, start firing, retries pile onto an already congested path, and a distant event on the ocean floor becomes a load spike you generated yourself.&lt;/p&gt;

&lt;h2&gt;
  
  
  A Pre-Mortem for Anything That Crosses an Ocean
&lt;/h2&gt;

&lt;p&gt;You cannot buy a cable ship, but you can stop assuming repair capacity is infinite. A few habits make the difference:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Map physical paths, not logical ones.&lt;/strong&gt; Run &lt;code&gt;mtr -rwc 100 &amp;lt;host&amp;gt;&lt;/code&gt; from where your users actually are, compare the hops with a public submarine cable map, and ask your providers which systems carry your traffic.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Budget timeouts for the detour.&lt;/strong&gt; Derive deadlines from a latency budget that survives an extra 100 to 150 ms of RTT instead of copying last month's p99.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Make retries polite.&lt;/strong&gt; Use exponential backoff with jitter and a retry budget, so a reroute does not turn into a denial-of-service attack you launched on yourself.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Rehearse the slow path.&lt;/strong&gt; On a staging host, &lt;code&gt;sudo tc qdisc add dev eth0 root netem delay 150ms 20ms loss 1%&lt;/code&gt; simulates a long detour; watch what breaks first, then clean up with &lt;code&gt;sudo tc qdisc del dev eth0 root&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Alert on latency steps by region.&lt;/strong&gt; A sudden, flat jump in RTT from one geography is the signature of a reroute, and error-rate alerts alone will sleep through it. Public trackers such as Cloudflare Radar usually show within hours whether the problem is yours or the whole region's.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Write the runbook in weeks, not hours.&lt;/strong&gt; Decide in advance what you will degrade for users behind a cut, such as upload sizes, media quality or sync frequency, because the fix might be a ship on the other side of a continent.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The Slowest Component Wins
&lt;/h2&gt;

&lt;p&gt;Our services recover in milliseconds, routing converges in minutes, and the seabed heals as fast as an old ship can clear its queue. That last number has been growing for more than a decade, and the incidents above show it does not care how many lines your architecture diagram has. Treat repair capacity like any other shared dependency you do not control: know where you lean on it, make the slow path survivable, and design as if one day your ticket will be third in line.&lt;/p&gt;

</description>
      <category>infrastructure</category>
      <category>networking</category>
      <category>sre</category>
    </item>
    <item>
      <title>The Signature Was Valid. The Software Wasn't.</title>
      <dc:creator>Sonia Bobrik</dc:creator>
      <pubDate>Sat, 10 Oct 2026 19:37:19 +0000</pubDate>
      <link>https://dev.to/sonia_bobrik_1939cdddd79d/the-signature-was-valid-the-software-wasnt-5684</link>
      <guid>https://dev.to/sonia_bobrik_1939cdddd79d/the-signature-was-valid-the-software-wasnt-5684</guid>
      <description>&lt;p&gt;In September 2015, WeChat shipped to the App Store with code that nobody at Tencent had written. So did a ride-hailing app, a music service, a business-card scanner and a long tail of other iPhone apps. Nobody had broken into those companies or touched their repositories. Somewhere on each of those teams, a developer frustrated by painfully slow downloads from Apple's servers had installed Xcode from a fast local cloud-storage share or a colleague's copy, and that copy carried a modified linker that stitched extra code into every app it built. The source was clean, the binaries were signed, and Apple's review approved them. That is precisely the blind spot that &lt;a href="https://www.halaltrip.com/user/profile/324715/the-hidden-life/" rel="noopener noreferrer"&gt;this essay on the hidden life of software provenance&lt;/a&gt; describes as operating on trust alone, and in most build pipelines it is wider than anyone likes to admit. This post is about the gap between the code you review and the bytes you actually ship, why a valid signature does not close it, and the cheap habits that do.&lt;/p&gt;

&lt;h2&gt;
  
  
  Ken Thompson Saw It Coming in 1983
&lt;/h2&gt;

&lt;p&gt;When Ken Thompson accepted the Turing Award in 1983, he spent his lecture describing a C compiler with two tricks. It recognized when it was compiling the Unix &lt;code&gt;login&lt;/code&gt; program and slipped in a backdoor password. It also recognized when it was compiling a new version of itself and quietly re-inserted both tricks. Once that binary existed, the compiler's source could be scrubbed perfectly clean and the backdoor would survive every rebuild. Thompson later confirmed that the trojan really did land in the login binary of a machine belonging to a Unix support group, although the poisoned compiler itself was never distributed. The lecture, published in 1984 as "Reflections on Trusting Trust," ends on a conclusion that has aged uncomfortably well: reading source code proves nothing about a binary unless you also trust everything that produced it.&lt;/p&gt;

&lt;p&gt;For more than thirty years, that attack lived mostly in lecture halls. XcodeGhost moved it into production. The idea was not even new in 2015: months earlier, documents leaked by Edward Snowden had described CIA-backed researchers claiming they had built a modified Xcode able to plant surveillance backdoors in any app compiled with it. What was new was the scale. Palo Alto Networks counted just five malicious apps that had ever made it into the App Store before that autumn, which is why BBC News reported XcodeGhost as &lt;a href="https://www.bbc.com/news/technology-34311203" rel="noopener noreferrer"&gt;the first large-scale attack on Apple's App Store&lt;/a&gt;, and estimates of infected apps eventually passed 4,000. Apple's remedy was telling: rebuild with a clean copy of Xcode, and verify that copy with Gatekeeper before trusting it again.&lt;/p&gt;

&lt;h2&gt;
  
  
  Signatures Answer "Who," and Attackers Love That
&lt;/h2&gt;

&lt;p&gt;Code signing was supposed to settle questions like these. Two incidents show why it cannot do the job alone.&lt;/p&gt;

&lt;p&gt;Between June and November 2018, attackers who had gotten inside ASUS pushed a backdoored version of its Live Update utility through the company's official update servers, signed with a legitimate ASUS certificate. Kaspersky, which uncovered the operation in January 2019 and named it ShadowHammer, found that more than 57,000 of its own users had installed the update and estimated the total reach at about a million people. The attackers only cared about roughly 600 of those machines, identified by MAC address hashes hardcoded into the malware. Every computer that checked the update concluded it genuinely came from ASUS, and every one of them was right.&lt;/p&gt;

&lt;p&gt;In 2023, the VoIP vendor 3CX, which says its software has more than 12 million users, shipped trojanized desktop apps for Windows and macOS. They were produced in 3CX's own compromised build environments, carried valid signatures and were served from 3CX's own website. Mandiant traced the intrusion to an employee who had installed X_TRADER, a futures-trading application retired in 2020 but still available for download in 2022, which had itself been trojanized. It was the first time Mandiant had seen one software supply chain attack directly produce another.&lt;/p&gt;

&lt;p&gt;A signature proves that someone holding a key approved a particular set of bytes. It says nothing about what happened between the commit and the key. If an attacker lives in that stretch, your signing step stops being a safeguard and becomes their laundering service.&lt;/p&gt;

&lt;h2&gt;
  
  
  Tags Lie, Hashes Don't
&lt;/h2&gt;

&lt;p&gt;The same failure shows up in tools developers touch every day. In March 2025, an attacker compromised tj-actions/changed-files, a GitHub Action used by more than 23,000 repositories, and retroactively moved its existing version tags to point at a single malicious commit. Workflows referencing a friendly tag such as &lt;code&gt;@v35&lt;/code&gt; silently started running code that dumped CI secrets into build logs, which on public repositories anyone can read. Nobody merged a pull request and nobody bumped a version; the tag simply started meaning something else. Workflows pinned to a full commit SHA kept running exactly what they had always run.&lt;/p&gt;

&lt;p&gt;The most encouraging story in this genre is also the most boring. From the end of January 2021, attackers periodically altered Codecov's Bash Uploader, a script that CI pipelines everywhere downloaded and executed on every run, so that it could ship data from those CI environments to a server outside Codecov's control. It was caught on April 1 by one customer who did something almost nobody does: compared the SHA256 of the freshly downloaded script with the checksum published on GitHub. The values did not match. Two months of silent exfiltration ended because one person ran one command.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Provenance Actually Adds
&lt;/h2&gt;

&lt;p&gt;Provenance turns the invisible stretch between commit and artifact into a claim someone else can check. In the SLSA framework (Supply-chain Levels for Software Artifacts, pronounced "salsa"), a provenance statement says, in effect: this exact artifact, identified by its digest, was produced by this builder, from this repository at this commit, by this workflow. Sigstore made signing such statements nearly free. Instead of guarding a long-lived private key that can be stolen, a CI job proves its identity through OIDC, receives a certificate that expires within minutes, and records the signature in a public transparency log where later tampering would stand out.&lt;/p&gt;

&lt;p&gt;None of this has to be built by hand anymore. &lt;a href="https://docs.github.com/en/actions/how-tos/secure-your-work/use-artifact-attestations/use-artifact-attestations" rel="noopener noreferrer"&gt;GitHub's guide to artifact attestations&lt;/a&gt; shows that a workflow needs only a few permissions, including &lt;code&gt;id-token: write&lt;/code&gt; and &lt;code&gt;attestations: write&lt;/code&gt;, plus one &lt;code&gt;actions/attest&lt;/code&gt; step pointed at its output; consumers can then run &lt;code&gt;gh attestation verify&lt;/code&gt; against the file and get a clear yes or no. That alone reaches SLSA Build Level 2. GitHub's immutable releases go further and lock a release tag to a single commit, which is exactly the guarantee tj-actions users assumed they already had. On the npm side, packages published with &lt;code&gt;npm publish --provenance&lt;/code&gt; link back to the commit and workflow that built them, and &lt;code&gt;npm audit signatures&lt;/code&gt; (npm 9.5 or later) reports how many of your installed dependencies carry verified registry signatures and attestations.&lt;/p&gt;

&lt;p&gt;Be honest about the limits. Provenance does not prove code is safe, and a malicious maintainer can publish malware with immaculate provenance. What it does is make the unexpected visible. A package that has shipped with attestations for two years and suddenly arrives without them, a binary built by a workflow you have never seen, an artifact whose digest matches no attested build: those are exactly the anomalies that XcodeGhost, ShadowHammer and the 3CX attack hid behind. Reproducible builds take the idea to its conclusion. Independent machines compile the same source and must produce bit-for-bit identical output, so no single build environment has to be trusted at all, which is why projects such as Debian and the Tor Browser have invested years in getting there.&lt;/p&gt;

&lt;h2&gt;
  
  
  A Provenance Audit You Can Run This Week
&lt;/h2&gt;

&lt;p&gt;You do not need a dedicated security team to start. Most of the protection comes from a handful of small, unglamorous changes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Pin third-party GitHub Actions to full commit SHAs&lt;/strong&gt; and keep the human-readable version in a trailing comment, or rely on publishers that use immutable releases.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Stop piping downloaded scripts straight into a shell in CI.&lt;/strong&gt; Fetch the file, compare its SHA256 with a value committed to your repository, and only then run it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Run &lt;code&gt;npm audit signatures&lt;/code&gt; in CI&lt;/strong&gt; and treat a dependency that used to ship attestations and suddenly does not as an incident until proven otherwise.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Attest your own release artifacts&lt;/strong&gt; and put the exact &lt;code&gt;gh attestation verify&lt;/code&gt; command in your README, so users can check your builds instead of taking them on faith.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Install compilers and SDKs only from the vendor's origin&lt;/strong&gt;, verify their signatures or checksums, and hold the toolchains baked into your CI images to the same rule.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Build one artifact twice on two different machines and diff the hashes.&lt;/strong&gt; The first mismatch you chase down will teach you more about your pipeline than a quarter of architecture meetings.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The Question Worth Asking
&lt;/h2&gt;

&lt;p&gt;Thompson needed three pages to show that source code is a promise, not proof. Four decades later, the tools for checking that promise are free and mostly boring: a pinned hash, an attestation, a one-line verify command in a README. What has changed is the question worth asking about everything that runs in your pipeline. It is no longer "is this signed?" It is "can I show where this came from, and would I notice if that changed tomorrow?" &lt;strong&gt;A signature tells you whom to blame. Provenance tells you what to believe.&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>cybersecurity</category>
      <category>security</category>
      <category>softwaredevelopment</category>
    </item>
    <item>
      <title>Passkeys Can't Be Phished. Your Fallbacks Can.</title>
      <dc:creator>Sonia Bobrik</dc:creator>
      <pubDate>Sat, 10 Oct 2026 19:33:54 +0000</pubDate>
      <link>https://dev.to/sonia_bobrik_1939cdddd79d/passkeys-cant-be-phished-your-fallbacks-can-1ffk</link>
      <guid>https://dev.to/sonia_bobrik_1939cdddd79d/passkeys-cant-be-phished-your-fallbacks-can-1ffk</guid>
      <description>&lt;p&gt;On July 20, 2022, at least 76 Cloudflare employees got the same text message within a single minute, each one pointing to a convincing copy of the company's Okta login page. Three of them typed in their usernames and passwords, which at most companies would be the first line of an incident report. At Cloudflare the attack went nowhere, because the second factor was a FIDO2 security key, and a key like that will not sign a login for a domain it was never registered with. If you want the plain-language case for making that kind of protection your default, this &lt;a href="https://bobriksonia.systeme.io/" rel="noopener noreferrer"&gt;practical upgrade path to passkeys and phishing-resistant MFA&lt;/a&gt; walks through it step by step, from password managers to recovery codes. This post picks up where that story usually ends: after the passkey button ships, when the other doors into the same account are still standing open.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why the Key Said No
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://blog.cloudflare.com/2022-07-sms-phishing-attacks/" rel="noopener noreferrer"&gt;Cloudflare's own write-up of the attack&lt;/a&gt; is worth reading for the mechanics alone. The lookalike domain was registered less than 40 minutes before the first text went out. Whatever a victim typed was relayed to the attacker over Telegram in real time, and the page then asked for a one-time code, so both could be replayed on the real login page before the code expired. Anyone who made it past that step was offered a download of AnyDesk, the remote access tool. Twilio, hit by a campaign with very similar fingerprints, had disclosed a breach the day before Cloudflare published.&lt;/p&gt;

&lt;p&gt;Against SMS codes or an authenticator app, a relay like that wins. A six-digit number has no idea which website it is being typed into, and neither does a distracted person holding a phone. A WebAuthn credential does know. The browser puts the page's origin into the data the authenticator signs, and the credential itself is scoped to a single relying party, so a key registered for the real login domain has nothing to offer a lookalike. Nobody has to spot the fake URL, because the protocol checks it for them. Cloudflare said that, like Google before it, it had not seen a successful phishing attack since hardware keys became mandatory. It also made a point of not punishing the three employees who were fooled, which is the right instinct. If a system fails whenever a human has a bad day, the system is the bug.&lt;/p&gt;

&lt;h2&gt;
  
  
  Attackers Don't Break the Lock. They Find Another Door.
&lt;/h2&gt;

&lt;p&gt;About a year later, a similar text-message lure reached Retool, and this time there was no hardware key at the end of the chain. One employee signed in on a fake identity portal. Then came a phone call from someone posing as IT, using what Retool describes as a deepfaked voice, and the employee read out one more one-time code. That code let the attacker add their own device to the employee's Okta account, which meant fresh MFA codes on demand from then on. The employee's Google Authenticator was also syncing codes to the cloud, so the hijacked Google account unlocked every other code as well. Retool's own conclusion was that its multi-factor setup had quietly collapsed into a single factor. By the time the company revoked every internal session, 27 cloud customer accounts had been taken over.&lt;/p&gt;

&lt;p&gt;Look at which step did the real damage. It wasn't the phished password, and it wasn't really the phished code either. It was what one phishable code was allowed to do: register a brand-new authenticator owned by the attacker. That single permission turned a moment of access into persistence.&lt;/p&gt;

&lt;p&gt;Then, in August 2025, Proofpoint published research by Yaniv Miron showing that accounts with FIDO credentials aren't automatically safe either. A dedicated Evilginx phishlet tells Microsoft Entra ID that the victim is browsing with Safari on Windows, a combination Entra ID doesn't support for FIDO sign-in. Entra ID does exactly what it was built to do: it shows an error and offers other methods. The victim picks the authenticator app, enters a code into the proxied page, and the attacker leaves with a session cookie. No cryptography was broken. The server simply believed a user agent string written by the attacker. Proofpoint said it hadn't seen the technique in the wild yet and that criminals still mostly go after accounts with weaker protection. That is the trend to plan for, because every passkey you ship makes the remaining fallbacks a more attractive target.&lt;/p&gt;

&lt;h2&gt;
  
  
  Your Real Security Level Is Your Weakest Path
&lt;/h2&gt;

&lt;p&gt;Put those three stories side by side and a rule falls out that is easy to state and uncomfortable to apply: &lt;strong&gt;an account is only as phishing-resistant as the weakest path that can create a session for it or change its credentials.&lt;/strong&gt; That covers login fallbacks, the flow that registers a new passkey or authenticator app, recovery by email or SMS, magic links, long-lived refresh tokens and whatever your support team can do from an admin panel. Most passkey rollouts add one strong path and leave every old one in place. That raises the average while leaving the minimum exactly where it was, and attackers only ever shop at the minimum.&lt;/p&gt;

&lt;h2&gt;
  
  
  Designing the Doors Around the Passkey
&lt;/h2&gt;

&lt;p&gt;You can't delete every fallback, because people lose phones and drop laptops in lakes. What you can do is make each remaining door as hard to open as the account deserves:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Let the account decide, not the client.&lt;/strong&gt; If an account has a passkey, a sign-in that reports "no WebAuthn here" should be steered to another phishing-resistant option, such as the cross-device flow where the user scans a QR code with their phone, or to a slower recovery path. It should not get a menu of codes to type. In a proxied session the attacker writes every header, the user agent included.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Gate enrollment like a wire transfer.&lt;/strong&gt; Registering a new passkey, adding an authenticator app or changing the phone number should require the strongest factor already on the account. Retool's attacker turned one spoken code into lasting access because enrollment accepted a weak factor.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Treat a downgrade as an event.&lt;/strong&gt; When an account that has used a passkey for months suddenly signs in with an SMS code from a new device, notify every enrolled device, require step-up before sensitive actions and consider a limited session until the user confirms from a trusted device.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Put time on recovery.&lt;/strong&gt; A recovery flow that finishes in seconds is just a login flow with fewer checks. A waiting period, alerts to every channel on file and a one-tap "this wasn't me" give the real owner a chance to cancel.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ask for a second passkey early.&lt;/strong&gt; Most recovery requests happen because someone lost their only credential. A second passkey, ideally a hardware key or one stored in a different ecosystem, keeps people away from the weak door in the first place.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Verify the origin against a fixed allowlist.&lt;/strong&gt; A page on any of your subdomains can request an assertion scoped to the parent domain, so the origin inside &lt;code&gt;clientDataJSON&lt;/code&gt; is what separates your login page from, say, a user-uploads subdomain. Libraries compare it only with the values you pass in, so hardcode them rather than reading them from request headers.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Make the Strong Door the Easy One
&lt;/h2&gt;

&lt;p&gt;None of this holds if the passkey path is a chore, because people route around friction and the fallback quietly becomes the main entrance. The encouraging part is that passkeys are now faster than what they replace. In &lt;a href="https://www.microsoft.com/en-us/security/blog/2025/05/01/pushing-passkeys-forward-microsofts-latest-updates-for-simpler-safer-sign-ins/" rel="noopener noreferrer"&gt;Microsoft's World Passkey Day update&lt;/a&gt;, the company reported that passkey sign-ins succeed about 98% of the time compared with 32% for passwords, and finish eight times faster than a password plus MFA. Microsoft also stopped presenting every sign-in method up front. Its sign-in screen now leads with the best method an account already has, a change that cut password use by more than 20% in its experiments. That is the list above applied to UX: defaults decide which door people walk through.&lt;/p&gt;

&lt;p&gt;On the web, the cheapest way to make passkeys the default is conditional mediation, which puts saved passkeys into the browser's autofill right next to saved passwords:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Pair with: &amp;lt;input name="username" autocomplete="username webauthn"&amp;gt;&lt;/span&gt;
&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;offerPasskeyAutofill&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;challenge&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;PublicKeyCredential&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;isConditionalMediationAvailable&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;PublicKeyCredential&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;isConditionalMediationAvailable&lt;/span&gt;&lt;span class="p"&gt;()))&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;assertion&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nb"&gt;navigator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;credentials&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;mediation&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;conditional&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;publicKey&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;challenge&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;rpId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;example.com&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;userVerification&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;preferred&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="c1"&gt;// Send the assertion to your server, which checks the challenge, origin and RP ID.&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Call it when the page loads so the request is already waiting. Users who have a passkey see it the moment they focus the username field, and nobody gets pushed through a separate ceremony they don't understand.&lt;/p&gt;

&lt;h2&gt;
  
  
  Audit the Doors Before Someone Else Does
&lt;/h2&gt;

&lt;p&gt;Here is a one-hour exercise for your next sprint. List every way a session can come into existence for one of your users and every way their credentials can change. Next to each entry, write down how it authenticates, then circle the weakest one. That line, not the passkey button on your login page, is your actual security level, and it is the line the next phishing kit will be written for. Cloudflare's three employees were fooled and the attack still failed, because the key was the only second factor its systems would accept. Build accounts where that is true, and a bad day for one of your users stays a bad day instead of turning into your breach notice.&lt;/p&gt;

&lt;p&gt;If you've already shipped passkeys, how did you handle fallback and recovery? Tell me in the comments what worked and what you had to roll back.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Crypto's $19 Billion Night Was a Distributed Systems Bug</title>
      <dc:creator>Sonia Bobrik</dc:creator>
      <pubDate>Sat, 10 Oct 2026 19:33:24 +0000</pubDate>
      <link>https://dev.to/sonia_bobrik_1939cdddd79d/cryptos-19-billion-night-was-a-distributed-systems-bug-1o32</link>
      <guid>https://dev.to/sonia_bobrik_1939cdddd79d/cryptos-19-billion-night-was-a-distributed-systems-bug-1o32</guid>
      <description>&lt;p&gt;On October 10, 2025, crypto exchanges force-closed more than $19 billion of leveraged positions belonging to roughly 1.6 million traders, the largest liquidation event the market has ever recorded. Most coverage told it as a macro story about a tariff threat, a nervous Friday, and too much leverage. Strip out the tickers, though, and the timeline reads like an incident report any backend team would recognize: a positive feedback loop, a source of truth that lied under load, and an emergency mechanism that made things worse the first time it actually ran. A good lens for taking it apart is &lt;a href="https://growinstaup.com/a-practical-research-driven-guide-to-avoiding/" rel="noopener noreferrer"&gt;this research-driven guide to avoiding the most common crypto mistakes&lt;/a&gt;, which treats market, counterparty, and technical risk as separate layers. That night all three failed at once, and the seams between them failed hardest.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Move Was Ordinary. The Cascade Was Not.
&lt;/h2&gt;

&lt;p&gt;The trigger was a post from President Trump announcing an additional 100% tariff on Chinese imports plus export controls on critical software. Bitcoin, which had set a record above $125,000 earlier that week, fell more than 12%. That is a brutal afternoon, but not an unprecedented one, and analysts at 21Shares later noted that Bitcoin's drawdown was smaller than in earlier major deleveraging events. The record lived in the plumbing. &lt;a href="https://www.bloomberg.com/news/articles/2025-10-10/crypto-sees-more-than-3-billion-in-liquidations-in-past-hour" rel="noopener noreferrer"&gt;Bloomberg's reporting on the liquidation wave&lt;/a&gt; described more than $7 billion of positions being sold in under an hour, and CoinGlass warned that even the record tally was probably an undercount, because Binance publishes only one liquidation order per second.&lt;/p&gt;

&lt;p&gt;Think about what that means operationally. During the most violent minutes the market has ever seen, its busiest venue was emitting sampled telemetry. Anyone who has debugged an outage with dashboards that only show averages knows the result: the worst minute of the year is also the least visible one. It skews the leaderboard too. Hyperliquid, where every liquidation lands on a public chain, topped CoinGlass's charts with about $10.3 billion, a comparison that quietly flatters venues that report less.&lt;/p&gt;

&lt;p&gt;Mechanically, a liquidation cascade is the textbook positive feedback loop. Falling prices push leveraged positions below their maintenance margin, the liquidation engine dumps that collateral into the order book, the selling pushes prices lower, and the next tier of positions crosses its threshold. It is a retry storm with money attached: every failure adds load to the exact component that caused it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Bug One: The Source of Truth Was the Thing on Fire
&lt;/h2&gt;

&lt;p&gt;The most instructive failure happened inside Binance's unified margin accounts, which let traders post assets such as Ethena's USDe and Binance's own staking tokens, wBETH and BNSOL, as collateral. The exchange valued that collateral largely from its own order books. As market makers pulled their quotes and transfers on and off the platform degraded, USDe printed as low as $0.65 on Binance while staying within a fraction of a percent of a dollar on other venues and on-chain. wBETH, a token backed by staked ether, briefly traded around $430 while ETH itself was above $3,800. Nothing had happened to the underlying assets. Something had happened to Binance's view of them, and positions that had lost no real value anywhere else were liquidated anyway.&lt;/p&gt;

&lt;p&gt;Every backend engineer has met this bug. It is the health check that asks the overloaded node whether it is healthy, or the cache that becomes the source of truth in the middle of a stampede. On a normal day, arbitrageurs behave like a reconciliation job, buying the cheap copy on one venue and redeeming it elsewhere until prices converge. That night the reconciliation job could not run, because moving funds on and off the exchange was exactly what had degraded. In some thin markets the price became whatever happened to be left in the book, and Binance later blamed several of the wildest wicks on stale limit orders dating back to 2019.&lt;/p&gt;

&lt;p&gt;The part that stings is the timing. On October 6, Binance had announced that from October 14 it would start factoring staking conversion ratios into how it priced wBETH and BNSOL. The fix was already sitting in the release train when the incident arrived. Afterward the exchange paid about $283 million in compensation, mixed redemption prices into its index, and added a soft price floor for USDe. The general lesson is the one you would apply to any critical read path: use independent sources, and treat disagreement between them as an incident rather than as a price.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;Quote&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;source&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nl"&gt;price&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="c1"&gt;// Never let the component under stress be the only witness to its own health.&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;markPrice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;quotes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Quote&lt;/span&gt;&lt;span class="p"&gt;[],&lt;/span&gt; &lt;span class="nx"&gt;maxDeviation&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;0.02&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;quotes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;price&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;pauseLiquidations&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;reason&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;too few independent sources&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;sorted&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;quotes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;q&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;q&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;price&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;sort&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;median&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;sorted&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;floor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;sorted&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)];&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;divergent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;quotes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;q&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;abs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;q&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;price&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;median&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="nx"&gt;median&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;maxDeviation&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="c1"&gt;// One venue printing $0.65 while the rest print $1.00 is an incident, not a price.&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;divergent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;names&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;divergent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;q&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;q&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;source&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;, &lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;price&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;median&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;pauseLiquidations&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;reason&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`divergent: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;names&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;price&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;median&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;pauseLiquidations&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;reason&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ok&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Pausing has failure modes of its own. Someone who can push a single venue far enough might try to freeze liquidations on purpose, so a real system pairs a check like this with alerting, time limits, and a human decision. But a paused liquidation can be resumed. A wrongful one can only be apologized for.&lt;/p&gt;

&lt;h2&gt;
  
  
  Bug Two: The Safety Valve Had Never Been Opened
&lt;/h2&gt;

&lt;p&gt;Perpetual futures venues keep one last mechanism for days when liquidations cannot keep up: auto-deleveraging, or ADL. When a losing account's margin is exhausted and the insurance backstop cannot absorb the hole, the venue closes positions on the winning side, starting with the most profitable and most leveraged, so the books still balance. On Hyperliquid, that Friday was the first time cross-margin ADL had fired in more than two years of operation. A later paper by Tarun Chitra of Gauntlet found that it closed about $2.1 billion of positions in twelve minutes.&lt;/p&gt;

&lt;p&gt;The trouble is who stands at the front of that queue. Many of the winning positions belonged to market makers and funds whose profitable shorts were hedges for exposure held somewhere else. ADL closed one leg and left the other standing, so books that had been neutral turned directional in the middle of a crash. Some firms rushed to reopen shorts to get back to neutral, adding fresh selling to a falling market, while others pulled back from quoting altogether. It is the infrastructure equivalent of a load shedder that evicts your healthiest tenants first.&lt;/p&gt;

&lt;p&gt;The deeper lesson is about code paths. Logic that runs once every two years is the least exercised code in your system, and nobody on call has ever watched it run in production. If your design leans on an emergency path, that path deserves game days and replays against realistic data, not just a paragraph in the docs.&lt;/p&gt;

&lt;h2&gt;
  
  
  Eight Months Earlier, the Same Lesson Cost $1.5 Billion
&lt;/h2&gt;

&lt;p&gt;October was a lesson about trusting the wrong source of data. February had already taught the same lesson about trusting the wrong source of code. On February 21, 2025, attackers drained more than 400,000 ETH from a Bybit cold wallet, and five days later &lt;a href="https://www.ic3.gov/PSA/2025/PSA250226" rel="noopener noreferrer"&gt;the FBI attributed the roughly $1.5 billion theft to North Korean operators it tracks as TraderTraitor&lt;/a&gt;. Chainalysis later put total crypto theft for all of 2025 at $3.4 billion, which means this single incident accounted for more than 40% of the year.&lt;/p&gt;

&lt;p&gt;Bybit's own infrastructure was never breached. The wallet was a Safe multisig, and investigators traced the compromise to a Safe developer's laptop that had been infected through social engineering more than two weeks earlier. Using stolen cloud credentials, the attackers modified JavaScript served from the S3 bucket behind the Safe web interface. The injected code activated only for Bybit's cold wallet and one test address, showed the signers what looked like a routine transfer, and passed their hardware wallets a different payload: a &lt;code&gt;delegatecall&lt;/code&gt; to a pre-deployed contract that overwrote the wallet's implementation pointer. About two minutes after the theft, the original files were put back.&lt;/p&gt;

&lt;p&gt;Two truths fall out of that. First, the presentation layer belongs to your trusted computing base. The hardware wallets did their job perfectly, which is to sign exactly what they are handed. Second, N-of-M approval only means something when the N paths are independent. Three signatures produced through one compromised browser bundle are, for security purposes, one signature.&lt;/p&gt;

&lt;h2&gt;
  
  
  Three Layers, One Graph
&lt;/h2&gt;

&lt;p&gt;The guide linked at the top is right that most people stuff crypto risk into a single bucket labeled "price." October 10 shows why separating the layers is only half the work. A market shock became a counterparty failure, one exchange mispricing its own collateral, through a technical design choice, and a second technical mechanism then turned it into a liquidity problem for everyone else. The layers are coupled, and the couplings are where the money disappears. Whether you hold crypto, build on it, or run systems that merely rhyme with it, the same review questions apply:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Name your source of truth.&lt;/strong&gt; For every number that can trigger an irreversible action, such as a liquidation, a signature, or a withdrawal, write down where it comes from and ask whether that source is the thing most likely to be on fire when you need it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Count independence, not replicas.&lt;/strong&gt; Three signers on one front end, five oracles fed by one venue, and two "separate" wallets behind one cloud account each count as one.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Rehearse the rare path.&lt;/strong&gt; Auto-deleveraging, emergency pauses, key rotation, and withdrawal halts deserve game days precisely because they almost never run.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Verify what you sign out of band.&lt;/strong&gt; Decode the payload on a separate machine, recompute the transaction hash, compare it with the hardware wallet's screen, and refuse any &lt;code&gt;delegatecall&lt;/code&gt; to a contract that is not on an explicit allowlist.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Assume your telemetry lies under load.&lt;/strong&gt; If a dashboard samples one event per second, the worst minute of the year will be the one you can see least.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Size for the cascade, not the move.&lt;/strong&gt; A 12% drop with a feedback loop behind it does not behave like a 12% drop.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The Boring Part Is the Point
&lt;/h2&gt;

&lt;p&gt;A year on, the uncomfortable thing about October 10 is how little of it was exotic. There was no zero-day, no broken cryptography, no consensus failure, and the major chains kept producing blocks the entire time. What broke was the ordinary scaffolding around them: a price feed that read from its own wreckage, a reconciliation path that went dark when it was needed most, a safety valve nobody had seen open, and a dashboard that sampled its way through the storm. The Bybit heist had the same shape, a web front end trusted far more than it deserved.&lt;/p&gt;

&lt;p&gt;That is good news for developers, because these are failure modes we already know how to engineer against. The next trigger might be a tariff, a hack, or a stablecoin wobble at 3 a.m. on a Sunday. Whether it becomes another $19 billion night will depend on the same decisions that decide whether a bad deploy becomes an outage: where your truth comes from, how independent your safeguards really are, and whether anyone has run the emergency path before the emergency.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>The 21st Field: What Security Vendors' Worst Days Teach Developers</title>
      <dc:creator>Sonia Bobrik</dc:creator>
      <pubDate>Sat, 03 Oct 2026 19:25:35 +0000</pubDate>
      <link>https://dev.to/sonia_bobrik_1939cdddd79d/the-21st-field-what-security-vendors-worst-days-teach-developers-1kc4</link>
      <guid>https://dev.to/sonia_bobrik_1939cdddd79d/the-21st-field-what-security-vendors-worst-days-teach-developers-1kc4</guid>
      <description>&lt;p&gt;At the end of February 2024, CrowdStrike shipped a new template for its Falcon sensor that declared 21 input fields, while the code feeding it supplied only 20. Nobody noticed for almost five months, because every rule written against the template used a wildcard for the last slot. Then, at 04:09 UTC on July 19, a rule arrived that actually checked field 21, and a kernel driver on millions of Windows machines tried to read a 21st value from an array that held 20. The financial aftermath of that morning, and of the Okta, F5 and SonicWall breaches on either side of it, is traced in &lt;a href="https://selar.com/909615c479" rel="noopener noreferrer"&gt;When the Security Vendor Becomes the Incident&lt;/a&gt;, a case study of the bills that investors, customers and courts sent afterward. The engineering story underneath those headlines is just as instructive, because nearly every root cause in it has a twin in ordinary application code.&lt;/p&gt;

&lt;p&gt;Security products are the code we trust most and inspect least. They run with kernel or administrator rights, update on someone else's schedule and sit in the path of every boot, login and packet. Read their post-mortems back to back and three patterns keep returning. None of them is exotic, and all three probably exist in the repository you will open tomorrow.&lt;/p&gt;

&lt;h2&gt;
  
  
  Configuration Is Code That Skipped the Pipeline
&lt;/h2&gt;

&lt;p&gt;CrowdStrike customers could stage and pin new sensor versions. Rapid Response Content, the behavioral rules the sensor pulls down between releases, was treated as data, and data went to every online host at once. Two safety nets failed on the way. The Content Validator checked the new rules against the template's definition of 21 fields, so it faithfully confirmed the wrong contract, and the interpreter had no runtime bounds check to catch what the validator missed. For many machines, recovery meant booting into Safe Mode or the Windows Recovery Environment, often typing in a BitLocker recovery key, and deleting one channel file by hand.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://blogs.microsoft.com/blog/2024/07/20/helping-our-customers-through-the-crowdstrike-outage/" rel="noopener noreferrer"&gt;Microsoft's own estimate&lt;/a&gt; put the affected devices at less than one percent of all Windows machines. Airlines still grounded flights and hospitals still postponed non-urgent care, because, as Microsoft noted, CrowdStrike is used by enterprises that run many critical services. Fleet percentage is a comforting number and an almost useless one: blast radius depends on which machines fail, not how many. Microsoft's longer answer has been architectural. It has been working with CrowdStrike and other vendors on a Windows endpoint security platform that lets antivirus and EDR products run in user mode, outside the kernel, and announced a private preview for partners in mid-2025.&lt;/p&gt;

&lt;p&gt;If that sounds like a kernel-driver problem, Cloudflare's outage on November 18, 2025 says otherwise. At 11:05 UTC, a deliberate ClickHouse permissions change made a metadata query, one that never filtered by database name, start returning duplicate rows. That query builds the feature file for Cloudflare's Bot Management model, which is regenerated every five minutes and pushed to the whole network. The file doubled in size and blew through a hard cap of 200 features, a limit set well above normal use because the proxy preallocates memory for them. The new Rust proxy, FL2, checked the count, got an error back and called &lt;code&gt;unwrap()&lt;/code&gt; on it, and the resulting panic surfaced as HTTP 5xx errors across Cloudflare's network. Customers still on the older proxy got no 5xx errors; instead every request received a bot score of zero, so sites with bot-blocking rules began turning away real visitors. Because only part of the database cluster had the change at first, good and bad files alternated, the network kept failing and recovering, and the team's first suspicion was a massive DDoS attack. Cloudflare called it its worst outage since 2019.&lt;/p&gt;

&lt;p&gt;Put the two incidents side by side and the lesson gets sharper. CrowdStrike's interpreter had no bounds check and read past the end of an array. Cloudflare's code had the check, in a memory-safe language, and the network went down anyway, because the only response it had to a failed check was to crash. Validation is half the job. The other half is deciding what happens to a bad file once you catch it, and "keep serving with the last good version" beats "panic" almost every time. Sixteen months apart, both failures had the same shape: a file produced by the vendor's own tooling and trusted because it came from inside, a consumer that assumed the file's shape, and a distribution system built for speed.&lt;/p&gt;

&lt;p&gt;The first item on Cloudflare's remediation list is to ingest its own generated configuration files with the same suspicion it applies to user input. Feature flags, WAF rules, ML feature lists and policy bundles all belong in that bucket, and plenty of teams still ship them through a faster, less guarded lane than code.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Front Door Was Somebody's Browser Profile
&lt;/h2&gt;

&lt;p&gt;Okta's October 2023 breach did not begin with an exploit. A service account for its customer support system had its username and password saved in an employee's personal Google profile, signed into Chrome on a company laptop, and Okta concluded that the credential most likely leaked through that personal account or device. Inside the support system sat HAR files, the recordings of browser sessions that customers upload so engineers can reproduce a bug. Some still held live session tokens, and the attacker used them to hijack the sessions of five customers. Okta's fixes read like a checklist for any SaaS team: personal profiles blocked in managed Chrome, and administrator session tokens bound to network location so a stolen one stops working from somewhere else. Within a week of Okta's disclosure, Cloudflare, one of the targeted customers, open-sourced a HAR sanitizer that strips session cookies and JSON Web Tokens in the browser before a file is shared.&lt;/p&gt;

&lt;p&gt;LastPass learned the same lesson at a higher price. After a 2022 intrusion into its development environment, attackers went after the home computer of a senior DevOps engineer, one of only four engineers who could reach the decryption keys for the company's production backups. A vulnerable third-party media package on that machine gave them remote code execution. A keylogger captured the master password as it was typed, after multi-factor authentication had already succeeded, and the corporate vault behind it held the keys to backups stored in Amazon S3. Those backups held copies of customer vault data.&lt;/p&gt;

&lt;p&gt;Neither attack broke any cryptography. Both walked through convenience: browser sync, a home media app, a debugging file with a live cookie inside. If an engineer can reach production from the same machine that runs weekend side projects, that machine is part of your threat model whether or not your architecture diagram shows it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Your Vendor's Build Room Is Part of Your Attack Surface
&lt;/h2&gt;

&lt;p&gt;F5 found intruders in its network on August 9, 2025. When it disclosed the breach in October, it said a nation-state actor had held long-term, persistent access to its BIG-IP product development environment and engineering knowledge management platform, and had taken portions of BIG-IP source code along with details of vulnerabilities its engineers were still working on. F5 reported no evidence of tampering with its build and release pipelines. The risk was quieter than a poisoned update: an adversary holding the source and the bug backlog can find and weaponize flaws faster than customers can patch them.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.cisa.gov/news-events/directives/ed-26-01-mitigate-vulnerabilities-f5-devices" rel="noopener noreferrer"&gt;CISA's Emergency Directive 26-01&lt;/a&gt; turned that risk into concrete work for federal agencies: inventory every BIG-IP product, check whether management interfaces are reachable from the public internet, install F5's updates within about a week, and disconnect devices that have reached end of support. Nothing on that list requires access to F5's systems. It is the half of a vendor breach that customers control.&lt;/p&gt;

&lt;p&gt;SonicWall's 2025 incident makes the same point from the storage side. In September, the company found that attackers had accessed firewall configuration files stored in its MySonicWall cloud backup service, and in November it attributed the intrusion to a state-sponsored actor. The credentials inside the files were encrypted, yet the files still described how each firewall was set up, which SonicWall itself warned could make targeted attacks easier, and its remediation guidance had customers reset admin passwords, VPN pre-shared keys and TOTP bindings anyway. A configuration backup is a secrets file with a friendlier extension.&lt;/p&gt;

&lt;h2&gt;
  
  
  What to Change Before Your Next Deploy
&lt;/h2&gt;

&lt;p&gt;None of these vendors were careless amateurs, which is exactly why their post-mortems are worth stealing from. Here is what they add up to for a team shipping its own software:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Map your privileged dependencies.&lt;/strong&gt; List every agent, driver, browser extension and appliance that runs with kernel, root or admin rights and updates itself, and write down who controls its update schedule.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Turn on update rings.&lt;/strong&gt; If a vendor lets you stage content updates as well as agent versions, put a few non-critical machines in the first ring and let them soak before the rest follow.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Distrust your own config.&lt;/strong&gt; Validate schema, field counts and size where a file is consumed, keep the last known-good version, fall back to it instead of crashing, and give every fast-moving feature a kill switch.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Price out the bad-boot day.&lt;/strong&gt; Know where recovery keys live, test out-of-band console access, and time how long it takes to fix ten machines by hand.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Scrub debug artifacts.&lt;/strong&gt; Strip cookies, tokens and authorization headers from HAR files and logs before they reach any support portal, and keep session tokens short-lived and bound to a device or network where your stack allows it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Shrink the management plane.&lt;/strong&gt; Keep admin interfaces off the public internet and patch edge appliances on a clock measured in days, not quarters.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Rotate after every vendor breach.&lt;/strong&gt; Include tokens, API keys and config secrets you believe are idle, since those are the ones nobody remembers to change.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Find Your 21st Field First
&lt;/h2&gt;

&lt;p&gt;Every company in these stories sells protection, and each one became, for a while, the thing its customers needed protecting from. That is not an argument for ripping out endpoint agents or identity providers, since a fleet without them is worse off. It is an argument for designing as if the most trusted code in your stack will someday misbehave: bounded inputs, a safe answer for when a bound is crossed, staged rollouts, scrubbed debug files, short-lived credentials and a recovery path someone has actually walked. Somewhere in your own system a template expects 21 fields and a caller sends 20. It is far cheaper to find it on a quiet Tuesday in a canary ring than at 04:09 on a Friday, on every machine you own.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>The Most Expensive Code You Ship Is the Admin Panel Nobody Reviews</title>
      <dc:creator>Sonia Bobrik</dc:creator>
      <pubDate>Sat, 03 Oct 2026 18:51:31 +0000</pubDate>
      <link>https://dev.to/sonia_bobrik_1939cdddd79d/the-most-expensive-code-you-ship-is-the-admin-panel-nobody-reviews-44k9</link>
      <guid>https://dev.to/sonia_bobrik_1939cdddd79d/the-most-expensive-code-you-ship-is-the-admin-panel-nobody-reviews-44k9</guid>
      <description>&lt;p&gt;Every product has a second application hiding behind it. It has no designer, no load tests and no on-call rotation, and its security model often amounts to a boolean called &lt;code&gt;is_admin&lt;/code&gt;. Support agents use it to look up customers, reset passwords and issue refunds, a few service accounts talk to it overnight, and nobody has read its pull requests with real curiosity since the sprint it was built in. Trace the costliest incidents of the past few years back to their first step and a surprising number start in exactly this kind of software, while the damage rarely stays inside IT: a recent analysis of &lt;a href="https://www.educba.com/cyberattack-financial-impact/" rel="noopener noreferrer"&gt;the financial impact of a cyberattack&lt;/a&gt; shows how quickly an intrusion becomes a cash flow and credit problem for the entire company. This post looks at the other end of that chain, the unglamorous internal tooling where the money starts leaking, and at what developers can change in it before the next quarter closes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Follow the Receipts
&lt;/h2&gt;

&lt;p&gt;Start with the cleanest example. In May 2025 Coinbase disclosed that criminals had bribed support contractors and employees outside the United States to pull customer records out of the company's own support tools. There was no exploit and no malware. The insiders used access they legitimately had to collect names, home addresses, government ID images, masked bank details and account balances for 69,461 customers, and the buyers used that data to phone victims while posing as Coinbase. The company refused a $20 million extortion demand, then booked $307 million in expenses tied to the incident in a single quarter. The detail worth sitting with is that Coinbase's own monitoring had flagged support staff &lt;strong&gt;accessing data without a business need&lt;/strong&gt; months before the extortion email arrived. The signal existed. A console that never asks why a record is being opened can only report abuse after it has happened.&lt;/p&gt;

&lt;p&gt;The help desk is the same story told over the phone. According to &lt;a href="https://www.bloomberg.com/news/articles/2023-09-16/mgm-resorts-hackers-broke-in-after-tricking-it-service-desk" rel="noopener noreferrer"&gt;Bloomberg's reporting on the MGM Resorts breach&lt;/a&gt;, the 2023 attack that disrupted MGM's resorts and casinos across the US began when attackers talked their way past the company's IT service desk. MGM later estimated a hit of roughly $100 million to its adjusted property EBITDAR, plus under $10 million in one-time costs. Clorox describes a similar opening move in the $380 million lawsuit it filed against Cognizant in July 2025, alleging that outsourced help desk agents reset passwords and MFA for an attacker without checking who was calling. Cognizant rejects the claims and says it was hired for a narrow scope of work. CISA and the FBI have described the same playbook in their joint advisory on Scattered Spider: impersonate an employee, call the help desk, walk away with a fresh password and a new MFA device. Whoever wins the lawsuit, the attack path was a reset workflow, and somebody designed that workflow.&lt;/p&gt;

&lt;p&gt;Then there are the accounts that aren't people. In 2023 an attacker entered Okta's customer support system with a service account that could view and update support cases. Okta's own root cause analysis found that the account's username and password had been saved to an employee's personal Google profile, signed in on a company laptop. Inside the support system sat HAR files that customers had uploaded for troubleshooting, session tokens included. The attacker reached files belonging to 134 customers and used them to hijack sessions at several of them. Okta's stock closed down about 11.5% on the day of disclosure, and more than $2 billion of market value was gone within two trading sessions.&lt;/p&gt;

&lt;p&gt;Finally, the integrations. In 2025 attackers spent months inside a Salesloft GitHub account, moved into the AWS environment behind its Drift chat product and left with the OAuth tokens that Drift customers had granted to connect it with Salesforce. Google's threat intelligence team said it was aware of at least 700 affected organizations. Because many of them used the integration for customer support, much of what leaked came from support tickets, and support tickets are where people paste things they shouldn't. Salesloft said the attackers pulled secrets such as AWS access keys, passwords and Snowflake tokens out of that data.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Attackers Shop in the Back Office
&lt;/h2&gt;

&lt;p&gt;None of this is bad luck. Internal tools concentrate privilege by design: they exist to do what the product deliberately won't let a user do, such as view anyone's data, change anyone's email, reset anyone's MFA or move anyone's money. They are run by big, frequently outsourced teams, which means more people who can be tricked, exhausted or bought. In the help desk's case, they are authenticated by a human listening to a voice on a phone line. And they rarely get the threat modeling that customer-facing code receives, because "only staff can reach it" feels like a security control when it is really a fact about the network.&lt;/p&gt;

&lt;p&gt;The economics are moving in the wrong direction. &lt;a href="https://www.ibm.com/think/x-force/2026-cost-of-a-data-breach-ai-adversaries-enterprise-risk" rel="noopener noreferrer"&gt;IBM's analysis of its 2026 Cost of a Data Breach findings&lt;/a&gt; puts the global average breach at a record $4.99 million and notes that fewer than half of organizations are actively securing non-human identities, the service accounts and tokens at the heart of the Okta and Drift stories. IBM's release on the same report adds that one in four malicious breaches is now AI-enabled, mostly through deepfake impersonation and AI-enabled malware, at an average cost of about $6 million. Put plainly, the caller asking your help desk for an MFA reset may not be a person at all, and "the agent recognized the voice" no longer counts as verification.&lt;/p&gt;

&lt;h2&gt;
  
  
  Treat the Back Office Like Production
&lt;/h2&gt;

&lt;p&gt;The fixes are not exotic. Most of them are ordinary engineering work that never reached a roadmap because the tool was "internal":&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Make every lookup carry a reason.&lt;/strong&gt; Tie record access to an open ticket or case ID, mask sensitive fields by default and log every reveal. Bulk harvesting becomes slow, noisy and attributable.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Put budgets on human queries.&lt;/strong&gt; Rate limits shouldn't stop at the public API. Alert when an agent opens far more accounts than their queue explains, or starts browsing customers nobody assigned to them.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Never let a voice authorize a reset.&lt;/strong&gt; MFA resets, email and phone changes and payout address updates should require a push to an already enrolled device, a callback to a number on file or a second approver, and the UI should make skipping that step impossible rather than merely discouraged.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Give machine credentials an expiry date.&lt;/strong&gt; Service accounts and OAuth grants need narrow scopes, short lifetimes, a named owner and a place in an inventory. A token that has worked for two years without anyone touching it is a finding, not a convenience.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Scrub secrets at the door.&lt;/strong&gt; Strip cookies and authorization headers from HAR files on upload, scan ticket bodies for keys and expire attachments when a case closes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Log for the worst day.&lt;/strong&gt; Keep audit trails the support organization cannot edit, store them where a stolen session cannot reach, and make "who viewed this customer last month" a query that returns in seconds.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;None of these items requires a new vendor. They require someone to open the admin panel's repository with the same suspicion they bring to the login page.&lt;/p&gt;

&lt;h2&gt;
  
  
  Pricing the Fix
&lt;/h2&gt;

&lt;p&gt;The hard part is rarely the code. It is convincing a roadmap that internal tooling deserves engineering time when no customer will ever notice the change. Money is the argument that lands, and the incidents above make it unusually easy to price. Ticket-scoped access, per-agent query budgets and a hardened reset flow are measured in sprints, not years. Set that against $307 million in one quarter at Coinbase or the $380 million claim Clorox took to court. IBM's data supplies a second lever: detection and escalation together with lost business make up 63% of breach costs, so an audit trail that answers questions in seconds is not paperwork. It is a direct cut to the most expensive line items.&lt;/p&gt;

&lt;p&gt;Phrase the risk the way finance already thinks. "The support console has broad read access" gets a polite nod and is forgotten by Friday. "One bribed contractor could export our customer list, and the last company this happened to spent $307 million cleaning up" gets a ticket scheduled. One sentence like that usually does more than a twelve-page threat model.&lt;/p&gt;

&lt;p&gt;The attackers in these stories did not need a zero-day. They needed a search box that asked no questions, a reset button that trusted a voice, a token nobody remembered issuing and a ticket queue full of pasted secrets. Every one of those was built on purpose by someone shipping under a deadline, which means the people best placed to take them apart are the developers reading this, ideally before an extortion email does the code review for them.&lt;/p&gt;

</description>
      <category>backend</category>
      <category>security</category>
      <category>software</category>
    </item>
    <item>
      <title>Your Podcast Habit Is Read-Only. Here's How to Give It a Write Path</title>
      <dc:creator>Sonia Bobrik</dc:creator>
      <pubDate>Sat, 03 Oct 2026 18:51:00 +0000</pubDate>
      <link>https://dev.to/sonia_bobrik_1939cdddd79d/your-podcast-habit-is-read-only-heres-how-to-give-it-a-write-path-3f1f</link>
      <guid>https://dev.to/sonia_bobrik_1939cdddd79d/your-podcast-habit-is-read-only-heres-how-to-give-it-a-write-path-3f1f</guid>
      <description>&lt;p&gt;Plenty of developers keep a podcast queue longer than their sprint backlog, and they burn through it the same way: earbuds in, playback at 1.5x, one eye on Slack. Here is a test worth running on yourself. Take any episode you finished last week, whether it was a three-hour deep dive into database internals or &lt;a href="https://podcastaddict.com/episode/https%3A%2F%2Fpodster.fm%2Fepisodes%2Fa1b70c81-506e-4f3d-91e2-d4c3459363d7%2Faudio.mp3%3Fmedia%3Drss&amp;amp;podcastId=7292577" rel="noopener noreferrer"&gt;the podcast episode you saved for your commute&lt;/a&gt;, and try to explain its three strongest ideas to a teammate without pressing play again. Most people recover one idea and a warm sense that it was good. That is not laziness. It is what happens when you treat audio as a read-only stream: bytes flow in, nothing gets written to disk, and the buffer is cleared by Thursday.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Listening Feels Like Learning
&lt;/h2&gt;

&lt;p&gt;Good podcasts are engineered to feel effortless. A skilled host asks the question you were about to ask, the guest answers with a crisp story, and the whole thing lands with the satisfying click of an idea that suddenly seems obvious. That click is the trap. Fluency feels like understanding, and the two are not the same thing.&lt;/p&gt;

&lt;p&gt;Harvard researchers measured this gap directly. For two weeks of an introductory physics course, students alternated between polished lectures from an experienced instructor and active-learning sessions that covered identical material. As the &lt;a href="https://news.harvard.edu/gazette/story/2019/09/study-shows-that-students-learn-more-when-taking-part-in-classrooms-that-employ-active-learning-strategies/" rel="noopener noreferrer"&gt;Harvard Gazette's write-up of the study&lt;/a&gt; explains, students felt they had learned more from the lectures, yet they scored higher on the tests that followed the active sessions. Lead author Louis Deslauriers put it bluntly: "Deep learning is hard work." The extra effort of the active sessions felt like confusion, so students mistook it for learning less.&lt;/p&gt;

&lt;p&gt;A well-produced podcast is the most fluent lecture ever invented, and it carries a handicap that a page of text does not: it is strictly linear. When a guest explains that they partitioned by tenant, pushed hot writes onto a queue and rebuilt reads from an event log, the next sentence arrives before you have finished drawing the diagram in your head. With a blog post you would scroll back and stare at that paragraph. With audio, the stream keeps moving and your half-built mental model quietly gets overwritten.&lt;/p&gt;

&lt;h2&gt;
  
  
  Speed Is Not the Real Problem
&lt;/h2&gt;

&lt;p&gt;The usual suspect is playback speed, and the evidence mostly clears it. In a study published in Applied Cognitive Psychology, a UCLA team had 231 students watch lecture videos at normal speed, 1.5x, 2x or 2.5x, with no pausing and no notes. Comprehension at 1.5x and 2x matched normal speed, both right away and a week later; only 2.5x clearly hurt. Eighty-five percent of the students the team surveyed already sped up their lectures. The most useful finding was a different one: watching twice at 2x beat watching once at normal speed, but only when the second pass was saved for later, right before the test, instead of coming straight after the first.&lt;/p&gt;

&lt;p&gt;That study used video rather than pure audio, so treat it as a strong hint rather than a law. The hint is still valuable. Speeding up is fine. What matters is what you do with the time you save, and the best use is a spaced second pass over the parts that mattered.&lt;/p&gt;

&lt;h2&gt;
  
  
  Add a Write Path: Retrieval Beats Replay
&lt;/h2&gt;

&lt;p&gt;If listening is a read operation, the write operation is retrieval: pulling an idea back out of your own head without looking. Psychologists have studied this for decades, and the results are lopsided. At Purdue, Jeffrey Karpicke and Janell Blunt had 200 students read science texts and then either build detailed concept maps or simply set the text aside and write down everything they could recall. As &lt;a href="https://www.nytimes.com/2011/01/21/science/21memory.html" rel="noopener noreferrer"&gt;The New York Times reported on the experiment&lt;/a&gt;, the recall group retained about 50 percent more a week later. Just as telling, students were poor judges of which method was actually working for them.&lt;/p&gt;

&lt;p&gt;There is also a clock running. Hermann Ebbinghaus showed back in the 1880s that unrehearsed memories fade fastest in the first hours and days after you meet them. An idea you have not retrieved by the end of the day is an idea you will probably have to hear again.&lt;/p&gt;

&lt;h2&gt;
  
  
  A Post-Episode Protocol That Takes Ten Minutes
&lt;/h2&gt;

&lt;p&gt;None of this requires a note-taking system with seventeen plugins. It requires a small habit loop wrapped around the listening you already do:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Ask a question before you press play.&lt;/strong&gt; "What would change how we do code review?" turns a passive stream into a search query, and your attention starts filtering for answers.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Bookmark instead of pausing.&lt;/strong&gt; Most modern players let you mark a timestamp; Podcast Addict, for example, supports bookmarks with notes, so you can flag the moment a guest explains their migration plan and keep walking.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Do a two-minute brain dump within the hour.&lt;/strong&gt; Close the app, write the three ideas you remember, then compare them with the show notes. The gaps tell you exactly which segment to replay.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Turn one idea into code within 48 hours.&lt;/strong&gt; Heard about property-based testing? Write one property for a parser you own. Heard about feature flags? Put one risky change behind a flag. A twenty-line spike teaches more than twenty pages of notes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Schedule the second pass.&lt;/strong&gt; A week later, reread your dump and replay only the bookmarked segments, at 2x if you like.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Teach it to someone.&lt;/strong&gt; A three-sentence summary in your team channel forces you to compress the idea, and compression is where understanding gets tested.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If the blank page stalls you, give the brain dump a fixed shape: one claim that surprised you, one you would argue with, and one thing you will try this week. The argument is the most valuable line, because disagreeing with a guest in writing is retrieval with a sharper edge.&lt;/p&gt;

&lt;h2&gt;
  
  
  Fewer Shows, Better Listening
&lt;/h2&gt;

&lt;p&gt;There is also a curation problem. A queue of forty unplayed episodes is not a learning plan; it is a to-do list that quietly generates guilt. Pick two or three shows whose ideas you would actually act on, and let everything else be entertainment. That is a perfectly good use of a podcast. Folding laundry to the story of a legendary outage counts as fun, and fun is allowed.&lt;/p&gt;

&lt;p&gt;Just be honest about which mode you are in. Learning mode needs at least part of your attention, which is why a dense conversation about distributed consensus will not survive being played under a debugging session. If you catch yourself rewinding the same thirty seconds three times, pause the episode, not the work you are paid for.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Episode Is the Input, Not the Output
&lt;/h2&gt;

&lt;p&gt;Podcasts are one of the best deals in a developer's learning budget: free, portable, and full of practitioners describing failures nobody puts in the docs. But the value does not transfer just because the audio played. It transfers when you retrieve, write and build. So switch off continuous playback in your player and let the silence after an episode become your cue. Spend two minutes writing down what you remember, pick one thing to try, and put it on tomorrow's list. Your queue will get shorter, and your head will finally start keeping what passes through it.&lt;/p&gt;

</description>
      <category>learning</category>
      <category>podcast</category>
      <category>productivity</category>
    </item>
  </channel>
</rss>
