Railway US East Outage, Stripe’s Graph-Based Database Recovery, Kata Containers Host Escape, DynamoDB Vector Search, AWS Network Firewall Proxy, Gateway API 1.6, and containerd 2.4
Try reloading the player or open this episode directly on YouTube.
This episode of Ship It Weekly explores the aftermath of outages, focusing on Railway's US East incident and its lingering issues with stale connections.
Now Playing
Railway US East Outage, Stripe’s Graph-Based Database Recovery, Kata Containers Host Escape, DynamoDB Vector Search, AWS Network Firewall Proxy, Gateway API 1.6, and containerd 2.4
Ship It Weekly
0:0015:52
Chapters
Jump to a section in this episode.
Speed & share
Transcript
Railway lost an upstream network path, recovered
it, and still kept having problems because stale
connections had moved onto the wrong network.
Stripe says it cut database pages by about 30
% by replacing hard-coded recovery logic with
graph search. And a critical Kata Containers
vulnerability let guest root become host root.
This week is mostly about what happens after
the obvious failure. I'm Brian Teller from Teller's
Tech, and this is Ship It Weekly. Welcome back
to Ship It Weekly, the show about the DevOps,
SRE, Cloud, platform, and security stories that
matter when you are the person keeping the thing
running at three in the morning. For the weekly
story list and source links, check out OnCallBrief.com
For past episodes and show notes, head
over to ShipItWeekly.fm. This week, Railway
published the RCA for a major U.S. East outage.
Stripe shared how it uses graph search and state
machines to automate database remediation. Kata
Containers patched a critical guest to host escape.
And DynamoDB now has native vector search. Then
we have three quick lightning stories and a closer
about learning cloud-native engineering by actually
working on real systems instead of just finishing
another tutorial. Let's get into it. First up,
Railway published the incident report for its
July 2nd US East outage. The incident started
with an upstream ISP problem. That alone is not
especially unusual. The more interesting part
is what happened next. Railway disconnected the
affected carrier. but in the process, it also
removed the site's last default route. Storage
traffic then fell back onto a management network
that was never intended to carry that load. Eventually,
the routing problem was fixed, but recovery did
not mean everything immediately went back to
normal. Some long-lived connections had already
established themselves over that slower management
network. they stayed there. So even after the
main route came back up, some traffic continued
using the wrong path. Railway also described
around 20,000 private network connections ending
up blackholed during the incident. This is
one of those failures where the original trigger
matters less than the state it leaves behind.
We tend to think of recovery as a binary thing.
Route is broken. Route is fixed. Incident over.
But distributed systems do not always reset themselves
just because the thing that caused the problem
has been corrected. Connections stay open. Caches
preserve bad information. Sessions remain pinned.
Retries build pressure somewhere else. And the
failover paths can quietly become the new steady
state. That is the lesson that I like here. When
you restore the control plane, you still need
to ask what data-plane state was created while
things were broken. What connections need to
be recycled? What caches need to expire? What
sessions need to be re-established? And what
fallback paths are still carrying traffic they
were never supposed to handle? The first fix
gets you out of the fire. The second part is
making sure the system actually returns to the
architecture you intended. Next, Stripe shared
how it reduced database paging by replacing a
lot of hard-coded remediation logic with something
much more dynamic. Stripe operates a large MongoDB
fleet, and like a lot of mature infrastructure,
recovery used to depend heavily on specific runbooks
and rules. If this condition happens, run this
action. If that action fails, try this other
one. That works. Until the number of possible
states gets large enough that the runbook itself
becomes a system you have to maintain. Stripe's
newer approach models remediation as a graph.
The current state of the database is a node.
Possible recovery actions are edges. And the
system can search for a safe path from the current
broken state toward a healthy one. They combine
that with state machines to track what is happening,
and Dijkstra's algorithm to find possible remediation
paths. The result, according to Stripe, is roughly
a 30% reduction in database-related pages.
They also reported around 200 fewer pages per
year and fewer days where shards stay unhealthy.
What I like about this is that it is not really
an AI story. It is an automation story. We sometimes
jump straight from manual runbooks to give an
agent access to production. There is a huge middle
ground between those two. You can model the problem,
you can encode valid state transitions, you can
define which actions are safe, and then let software
calculate the recovery path without making the
recovery system completely open-ended. That
is a much more interesting form of automation
to me. It still gives the system flexibility,
but the flexibility exists inside boundaries
engineers actually defined. And just as importantly,
the recovery logic becomes something you can
reason about. You can inspect the graph. You
can test transitions. You can understand why
the system selected one path instead of another.
Automation gets much more useful when it reduces
toil without also reducing explainability. Third,
Kata Containers patched a critical guest -to
-host escape. The vulnerability affected the
runtime-rs virtio-fs path. In the affected
configuration, root inside the guest could cross
the isolation boundary and end up executing as
root on the host. That is about as bad as container
isolation bugs get. Kata exists specifically
to strengthen the boundary between a workload
and the machine underneath it. Instead of relying
only on normal container isolation, workloads
run inside lightweight virtual machines. So when
a vulnerability crosses from guest root to host
root, it is attacking the exact security property
people adopted Kata to get. Affected versions
run through 3.30.0. The fix is in 3.31.0.
The practical takeaway here is pretty simple.
If you are running Kata Containers, this is not
a patch that I would leave sitting in the normal
backlog. But there is a broader point too. Isolation
technology changes the attack surface. It does
not remove it. A VM boundary is stronger than
a namespace boundary in a lot of scenarios. But
virtio, shared filesystems, device emulation,
runtime components, and the glue connecting guest
and host all become part of that trusted boundary.
Every time that we say that something is sandboxed,
the next question should be, by what? And what
still crosses that boundary? Isolation is not
a checkbox. It is an architecture. DynamoDB now
supports native vector search. That means that
applications can store embeddings and run similarity
searches without automatically reaching for a
separate vector database. For teams already using
DynamoDB, that can remove a surprising amount
of architecture. Today, a common pattern is to
store application data in one system, generate
embeddings, write those embeddings somewhere
else, and then keep both stores synchronized.
Now you can potentially keep the primary data
and vector representation closer together. That
is attractive for things like semantic search,
recommendations, retrieval-augmented generation,
and agent memory. But I would not read this as
vector databases are dead. A specialized vector
engine may still be the right answer if vector
search is the core of the workload or if you
need capabilities DynamoDB does not provide.
The interesting part is that vector search is
becoming another normal database feature. We
have already watched this happen with JSON support,
full-text search, caching, analytics, and other
capabilities that once demanded separate systems.
That usually leads to a good architecture question.
Do I actually need another service? Every additional
database creates another backup strategy, another
availability model, another security boundary,
another cost center, and another thing someone
has to understand during an outage. Sometimes
that complexity is justified. Sometimes the best
infrastructure decision is deleting a box from
the diagram. Quick lightning round. First, AWS
brought explicit proxy functionality into network
firewall. That gives teams another way to control
outbound traffic while keeping firewall rules,
intrusion detection, TLS inspection, and workload
-aware controls in the same general system. There
is also a new no-source-preservation mode that
can work with NAT Gateway. Useful, but as always
with AWS networking, look closely at the traffic
path and processing costs before you decide the
cleaner diagram is also the cheaper one. Second,
Gateway API 1.6 makes TCPRoute and UDPRoute stable.
That matters for workloads that are not HTTP.
Databases, queues, game servers, DNS. and other
Layer 4 services can now use stable Gateway API
resources instead of treating Gateway API as
mostly an HTTP routing story. And third, containerd
The thing that stuck with me most from this episode is that fixing the thing that failed is not always the same as recovering the system.
Railway is a really good example of that. The original problem was understandable enough: an upstream network issue, a routing change, and suddenly the site had lost its last default route. But even after the route came back, the system was not really back. Connections had already moved onto a management network that was never supposed to carry that traffic. Some of them stayed there. Other private-network connections ended up blackholed. The triggering failure was gone, but the state created by the failure was still hanging around.
I think we sometimes underestimate how much state exists outside the thing we are actively repairing. We fix a route and assume traffic will normalize. We restore a database and assume clients will reconnect cleanly. We recover a dependency and assume retries will settle down. But connections, caches, sessions, queues, circuit breakers, DNS, and failover paths may all have reacted to the outage. Recovery has to include those reactions too.
That is probably the broader lesson here. Incident response cannot stop at “the dashboard is green again.” You have to ask whether the system actually returned to its intended steady state. Are clients still pinned to a degraded path? Did a temporary fallback quietly become permanent? Is a retry storm still pushing load somewhere unexpected? Did anything make a decision during the incident that it will not automatically undo?
The Stripe story approached the same problem from another direction, and I really liked it because it was an automation story without immediately becoming an AI story. Stripe modeled database recovery as a graph. The current condition is a state, remediation steps move you between states, and software can calculate a valid path back toward health. That is a very different idea from simply giving an agent production credentials and telling it to fix things.
There is a lot of useful space between a manual runbook and fully autonomous remediation. State machines, policy engines, dependency graphs, health models, and constrained automation are not as exciting to talk about as an AI agent running your infrastructure, but they give you something incredibly valuable: boundaries. You can define which transitions are allowed, test them, understand why a decision was made, and keep the recovery process explainable. Stripe says that approach cut database pages by roughly 30 percent. That is automation doing exactly what I want automation to do: remove repetitive toil without making the system harder to understand.
The Kata Containers vulnerability is another reminder that boundaries only mean something if you understand what actually crosses them. Kata gives workloads a much stronger isolation model by putting them inside lightweight virtual machines. That is useful. But the host and guest still have to communicate somehow. Filesystems, virtio devices, runtime components, and other interfaces become part of the trusted surface. In this case, a bug in that boundary could let guest root reach host root.
We use words like sandbox, isolated, private, and secure very casually in infrastructure. Those words are really shorthand for an architecture. A sandbox is only as strong as the interfaces leading out of it. A private network is only private based on the routes and controls around it. A container is isolated according to a collection of kernel, runtime, filesystem, and device boundaries. The useful question is rarely “is this isolated?” It is “what still crosses the isolation boundary, and what happens if that component is compromised?”
DynamoDB adding vector search is almost the opposite kind of story, but I think it fits the episode surprisingly well. Sometimes reliability comes from adding stronger boundaries. Other times it comes from deleting unnecessary ones. If DynamoDB already stores the application data and can now handle the vector workload you need, maybe you do not need another database, another synchronization process, another backup policy, another set of credentials, and another thing for somebody to understand at three in the morning.
There is always a temptation in platform engineering to solve a new requirement with a new box on the architecture diagram. Sometimes that is absolutely the right answer. Specialized systems exist for a reason. But every additional component creates operational surface area. The best architecture is not necessarily the one with the most purpose-built services. Sometimes it is the one where you can safely remove three arrows and a database.
And the human closer connects to all of this more than it might seem. Tutorials teach you what a system looks like when every assumption is correct. Engineering starts when one of those assumptions is wrong. The version is different. The collector runs but sends nothing. The permissions look right but are not. The documentation describes an older release. That is when you stop following instructions and start reasoning about the system.
That ability to reason is what connects every story this week. Railway had to reason about the state left behind after the route was repaired. Stripe encoded reasoning about recovery paths into software. Kata reminds us to reason about where isolation really begins and ends. DynamoDB forces the architecture question of whether another service actually buys enough value to justify its operational cost.
Tools matter. Runbooks matter. Automation matters. But the thing that keeps showing up in production is judgment.
Getting the obvious failure to disappear is one step.
Understanding what the system became while it was failing is usually the harder one.
📝 Notes
Show Notes
This week on Ship It Weekly: Railway explains how an upstream network problem turned into a much larger US East outage, including storage traffic falling back onto the management network and stale connections continuing to cause problems after routing recovered. Stripe shares how graph search and state machines helped cut database pager volume by about 30 percent. Kata Containers patches a critical guest-to-host escape, and DynamoDB adds native vector search.
The bigger theme this week is what happens after the obvious failure. Fixing the route does not necessarily clear the connections created while it was broken. Automating recovery does not have to mean handing an AI agent unrestricted production access. And stronger isolation does not eliminate the components that still cross the guest-host boundary.
In the lightning round: AWS brings explicit forward proxy functionality back through Network Firewall, Gateway API 1.6 moves TCPRoute and UDPRoute to stable, and containerd 2.4 enters beta with new functionality alongside breaking changes worth finding before your next runtime upgrade.
The thing that stuck with me most from this episode is that fixing the thing that failed is not always the same as recovering the system.
Railway is a really good example of that. The original problem was understandable enough: an upstream network issue, a routing change, and suddenly the site had lost its last default route. But even after the route came back, the system was not really back. Connections had already moved onto a management network that was never supposed to carry that traffic. Some of them stayed there. Other private-network connections ended up blackholed. The triggering failure was gone, but the state created by the failure was still hanging around.
I think we sometimes underestimate how much state exists outside the thing we are actively repairing. We fix a route and assume traffic will normalize. We restore a database and assume clients will reconnect cleanly. We recover a dependency and assume retries will settle down. But connections, caches, sessions, queues, circuit breakers, DNS, and failover paths may all have reacted to the outage. Recovery has to include those reactions too.
That is probably the broader lesson here. Incident response cannot stop at “the dashboard is green again.” You have to ask whether the system actually returned to its intended steady state. Are clients still pinned to a degraded path? Did a temporary fallback quietly become permanent? Is a retry storm still pushing load somewhere unexpected? Did anything make a decision during the incident that it will not automatically undo?
The Stripe story approached the same problem from another direction, and I really liked it because it was an automation story without immediately becoming an AI story. Stripe modeled database recovery as a graph. The current condition is a state, remediation steps move you between states, and software can calculate a valid path back toward health. That is a very different idea from simply giving an agent production credentials and telling it to fix things.
There is a lot of useful space between a manual runbook and fully autonomous remediation. State machines, policy engines, dependency graphs, health models, and constrained automation are not as exciting to talk about as an AI agent running your infrastructure, but they give you something incredibly valuable: boundaries. You can define which transitions are allowed, test them, understand why a decision was made, and keep the recovery process explainable. Stripe says that approach cut database pages by roughly 30 percent. That is automation doing exactly what I want automation to do: remove repetitive toil without making the system harder to understand.
The Kata Containers vulnerability is another reminder that boundaries only mean something if you understand what actually crosses them. Kata gives workloads a much stronger isolation model by putting them inside lightweight virtual machines. That is useful. But the host and guest still have to communicate somehow. Filesystems, virtio devices, runtime components, and other interfaces become part of the trusted surface. In this case, a bug in that boundary could let guest root reach host root.
We use words like sandbox, isolated, private, and secure very casually in infrastructure. Those words are really shorthand for an architecture. A sandbox is only as strong as the interfaces leading out of it. A private network is only private based on the routes and controls around it. A container is isolated according to a collection of kernel, runtime, filesystem, and device boundaries. The useful question is rarely “is this isolated?” It is “what still crosses the isolation boundary, and what happens if that component is compromised?”
DynamoDB adding vector search is almost the opposite kind of story, but I think it fits the episode surprisingly well. Sometimes reliability comes from adding stronger boundaries. Other times it comes from deleting unnecessary ones. If DynamoDB already stores the application data and can now handle the vector workload you need, maybe you do not need another database, another synchronization process, another backup policy, another set of credentials, and another thing for somebody to understand at three in the morning.
There is always a temptation in platform engineering to solve a new requirement with a new box on the architecture diagram. Sometimes that is absolutely the right answer. Specialized systems exist for a reason. But every additional component creates operational surface area. The best architecture is not necessarily the one with the most purpose-built services. Sometimes it is the one where you can safely remove three arrows and a database.
And the human closer connects to all of this more than it might seem. Tutorials teach you what a system looks like when every assumption is correct. Engineering starts when one of those assumptions is wrong. The version is different. The collector runs but sends nothing. The permissions look right but are not. The documentation describes an older release. That is when you stop following instructions and start reasoning about the system.
That ability to reason is what connects every story this week. Railway had to reason about the state left behind after the route was repaired. Stripe encoded reasoning about recovery paths into software. Kata reminds us to reason about where isolation really begins and ends. DynamoDB forces the architecture question of whether another service actually buys enough value to justify its operational cost.
Tools matter. Runbooks matter. Automation matters. But the thing that keeps showing up in production is judgment.
Getting the obvious failure to disappear is one step.
Understanding what the system became while it was failing is usually the harder one.