Last time I said we’d look at patching, because it’s the one form of drift people actually think about. Nobody forgets that patching exists. It’s on every compliance checklist, every audit, every security review. And yet in my experience it generates more arguments about responsibility than almost anything else on a platform.
That’s the interesting part. It isn’t a knowledge problem. Everyone knows patching needs to happen. It’s an ownership problem. On a shared platform, patching splits across a line that nobody drew clearly, and both sides of that line quietly assume the other one has it covered.
So this post is in two halves. First, the patching the platform team genuinely owns and has to operate properly. Then the harder half: the patching that sits in the seam between the platform team and the workload teams, where the real arguments live.
The half the platform owns
Let’s start with the part that’s at least clear in principle. If you run shared platform infrastructure, you own patching it. Nobody else is going to.
The trap here isn’t confusion about ownership. It’s that cloud lulls you into thinking patching went away. A lot of the platform genuinely is patched for you now. Managed services get patched by Microsoft. Managed DevOps Pools run in Microsoft-managed subscriptions with provisioning, scaling, and patching handled for you. Plenty of the estate really has moved from scheduled downtime to continuous updates, and that’s a genuine gain.
The problem is the word “a lot.” Not all. And the gap between “most of it is handled” and “all of it is handled” is exactly where things rot, because the leftovers are easy to forget precisely because so much else is automatic.
The pieces that are still yours tend to be:
Node images. Your AKS node pools run an OS image that needs updating. Azure can automate a good deal of this, but the configuration of how and when is yours, and “we assumed node auto-upgrade was on” is a sentence I’ve heard after the fact more than once. Auto-upgrade being available is not the same as it being enabled and verified.
Custom images. The moment you build your own VM or container images, whether that’s a golden image or a custom pipeline runner image, you own the patch currency of everything baked into them. Microsoft patches the platform. It does not patch the image you built on top of it. Build your own runner image and you’ve taken on the job of keeping its contents current, which is a real recurring cost that’s easy to accept without noticing.
Anything still running as a VM. If you’ve got platform-level VMs, jump boxes, self-hosted agents you haven’t migrated, appliances, they patch the way servers have always patched. Cloud didn’t change that. It just made it easier to forget they’re there.
None of this is hard. It’s just easy to drop, because the automatic majority creates a false sense that patching is a solved problem. The fix is boring and it’s the same fix as the last post: name the owner, make the currency visible, and treat “is this actually patching itself, or did we just assume it was” as a question somebody answers on a cadence rather than after an incident.
The half nobody owns
Now the difficult part, and the reason this post exists.
On a shared platform, there’s a layer that sits between what the platform team runs and what the workload teams run, and patching responsibility across that layer is almost never written down. It gets assumed. And when both sides assume, the same thing happens every time: each side believes the other one has it.
The classic example is the container. The platform team provides a base image. A workload team builds their application on top of it. A CVE lands in a library in the base image. Who patches it?
The platform team’s view: we published a fixed base image, our job is done, the workload teams need to rebuild on it.
The workload team’s view: the base image is platform’s, so the vulnerability in it is platform’s to fix, and anyway nobody told us a new one was out.
Both are being reasonable. Both are pointing at the other. And the vulnerable container keeps running in production while the argument plays out, because the one thing neither side is doing is patching it.
You can rerun this exact pattern across the whole platform:
- The AKS cluster is patched by the platform team, but the workloads running on it, and whether they tolerate a node cycling, are the workload team’s problem. Who owns the coordination?
- The platform provides a hardened image with an agent baked in. The agent needs updating. Is that a platform push or a workload rebuild?
- A shared component, an ingress controller, a service mesh, a logging sidecar, needs a security update that requires every consuming team to redeploy. Who chases them?
In every case the technical fix is trivial. The failure is that no decision was ever made about who’s responsible, so the responsibility falls into the gap between two teams who each had reasonable grounds to think it wasn’t theirs.
When Microsoft ends the runtime out from under you
There’s a version of this that’s worse than a CVE, because the clock isn’t yours to set. It’s runtime lifecycle.
Take App Service. It follows the community support timeline for each language runtime, so when Node or Python reaches end of life in the community, App Service stops patching that runtime too. Your app doesn’t break the moment support ends, it keeps running, but the runtime underneath it is now unpatched, and eventually the version disappears from the platform entirely and startup fails. Microsoft does give you notice, at least six months for an affected runtime, sent to the subscription owners. And there’s the crack. The notice goes to whoever owns the subscription. Does that person know which apps are on the affected runtime? Do they know which workload team owns each one? In a lot of organisations, the answer to both is no, and the email gets filed under “someone else’s problem” until the version stops working.
This is a genuinely different beast from patching. A patch is something you apply on your schedule. A runtime retirement is a forced upgrade on Microsoft’s schedule, and the fix usually isn’t a patch at all, it’s a version bump that can carry real breaking changes. Moving a workload from one major version of Node or Python to the next isn’t a config toggle. It’s a code change that has to be tested, which means it’s unambiguously the workload team’s work, not the platform team’s.
So who owns it? Split it the same way as everything else, but be honest about where each piece lands:
- Knowing. The platform team is best placed to own the radar. You can enumerate what’s running on which runtime across the estate, catch the deprecation notices, and translate “Python 3.9 retires in October” into “these six apps, owned by these four teams, are affected.” No workload team has that estate-wide view. If the platform team doesn’t own the watching, nobody does, and the six-month notice gets discovered with six weeks left.
- Fixing. This is the workload team’s, without argument. Only they can bump the version, deal with the breaking changes, and test that their app still works. The platform team cannot and should not be doing this on their behalf.
- Landing it. Shared again. The platform team owns the deadline and the chase; the workload team owns hitting it. And this is the one that needs a real expectation attached, because “you’ve got six months” reliably becomes “we’ve got six weeks” without someone tracking the runway.
The best-practice version of this is unglamorous and it’s the same shape as the last post: make runtime currency visible and owned rather than discovered. Keep an inventory of what runs on what, so a retirement notice maps to owners in minutes rather than a panicked audit. Don’t pin to a specific minor version unless you’ve consciously chosen to own that currency yourself, because pinning opts you out of the platform’s own patching. And if a workload genuinely needs to control its exact runtime, that’s what custom containers are for, but then the currency of that container is yours, not Microsoft’s, which is just the custom-image point from earlier wearing a different hat.
This is a design decision, not a personality problem
Here’s the framing I keep coming back to across this whole series. When patching falls through the cracks, the instinct is to look for who dropped the ball. That’s the wrong question, and it’s a corrosive one, because it turns an operating model gap into a blame exercise and the teams learn to defend rather than fix.
The real problem is that a decision was never made. The responsibility boundary for patching was left implicit, and implicit boundaries always fail in exactly the place two teams meet. Nobody dropped the ball. The ball was never handed to anyone.
So the fix isn’t a better patching tool. It’s a decision, written down, about where the line sits. For every shared thing on the platform, somebody should be able to answer:
- Who is responsible for knowing a patch is needed?
- Who is responsible for producing the fix, the new base image, the updated component, the config change?
- Who is responsible for it actually landing in production, including chasing the teams who have to act?
That last one is the one everyone forgets. Producing a fixed image isn’t patching. It’s patching when it’s running everywhere it needs to be, and somebody has to own the distance between “available” and “deployed.” On a shared platform that almost always means the platform team owns the notification and the artifact, and the workload teams own the redeploy, with an agreed expectation of how fast that has to happen and who follows up when it doesn’t.
None of that is exotic. It’s just a decision that most platforms never explicitly make, and then relitigate every single time a CVE lands.
The point
Patching is the drift everyone remembers to worry about, and it still goes wrong, which tells you the problem was never awareness. It’s ownership. The platform team’s own patching gets dropped because automation creates a false sense that it’s all handled. The shared-layer patching gets dropped because the boundary was never drawn and both sides assumed the other had it.
Both failures have the same root, and it’s the root of this entire series: the platform you operate quietly diverges from the platform you designed, not because anyone was negligent, but because the decisions about who owns what were never made explicit, so they got made by default. And default ownership means no ownership.
Next time I want to stay on that theme but move to identity, because if patching is the drift people remember, identity lifecycle is the drift people actively look away from, and it’s where the gap between “designed” and “operated” gets genuinely dangerous.