Monday, April 21, 2025

Platform Engineering Ate DevOps

The rebrand is complete. Somewhere along the way, every DevOps team became a platform team, every runbook became a golden path, and every engineer with a Terraform repo started calling it an internal developer platform. DevOps didn't die. It got a new job title and a bigger budget.

I'm not mocking it. The shift is real, and mostly it's an improvement. But if you're a TPM or a security person trying to figure out what changed and what you're supposed to do about it, it's worth being clear-eyed about what platform engineering actually is versus what the conference talks say it is.

What it actually is: a product discipline applied to internal tooling. Instead of each team building its own deployment pipeline, its own observability setup, its own way of provisioning a database, one team builds the paved road and everyone else drives on it. The pitch is that developers spend less time on undifferentiated plumbing and more time on the thing the company actually sells.

That pitch is mostly true. The part nobody puts on the slide is that the paved road has tolls. Somebody has to build the platform, maintain the platform, secure the platform, and — hardest of all — convince teams to actually use it instead of building their own thing anyway. Platform engineering done badly is just centralized DevOps with better marketing and slower ticket queues.

For TPMs, the work didn't change as much as the vocabulary did. You're still reducing toil, still shepherding migrations, still translating between the people who build the thing and the people who depend on it. The difference is the interface: instead of coordinating fifteen teams' deployment practices, you're managing one platform's roadmap and its adoption curve. The politics moved up a level. The spreadsheets got bigger.

For security folks, though, the platform shift is the best thing that happened in a decade — and most of us haven't fully grasped it yet.

Here's why: "shift left" mostly failed. Telling every developer to become a security expert didn't work, because developers have a job and it's not security. What works is putting the guardrails *in the platform* so the secure path is the easy path. Container images scanned by default. Secrets injected, never hardcoded — because the platform doesn't give you another option. Network policies applied at deploy time, not as a wiki page nobody reads.

The platform is where security goes from advice to architecture. That's a profound change, and it's the part of the rebrand that actually matters.

But — and there's always a but — the platform is also a single point of failure and a single point of compromise. When every team deploys through the same pipeline, whoever owns the pipeline owns the kingdom. Supply chain attacks, poisoned base images, a misconfigured admission controller: the blast radius of a platform compromise is the entire engineering org. We traded fifteen small attack surfaces for one enormous one, and we'd better be securing it like the crown jewels.

So the honest version of the story: platform engineering is DevOps with product management, and that's genuinely better. It gives security a place to live that isn't a checklist. But it concentrates risk, and it only works if the platform team treats security as a feature of the platform rather than a tax on its users.

The rebrand is complete. Now comes the hard part: making the thing worthy of the name.

Wednesday, April 9, 2025

The Backlog Is a Garden, Not a Warehouse

Written by Alanna Gray, 2025

The Backlog Is a Garden, Not a Warehouse

Most backlogs I have ever seen — and I have audited, inherited, and run more of them than I can count — are managed like warehouses. Everything anyone ever requested gets received, labeled, and shelved. Storage feels free. Nobody throws anything away, because throwing things away feels like a decision, and decisions can be argued with. So the inventory grows, and quietly, it rots. Items written for a system that no longer exists. Requests from people who have left the company. Features whose whole reason walked out the door two reorganizations ago. The list gets longer, the team gets more cynical, and eventually nobody believes the backlog at all — including the people who maintain it. A list nobody believes is worse than no list. It is process theater with a search box.

A garden works on the opposite principle. A garden is finite on purpose. Things are planted deliberately, tended on a schedule, pruned without sentimentality, and — this is the part warehouse managers can't stand — some things are simply not planted at all. What isn't tended in a garden dies honestly, out in the open, instead of sitting on a shelf pretending to be alive for three years. Your backlog should be so lucky.

Prune on a schedule, not on a whim

Gardeners don't prune when they feel brave. They prune when the season says to. Steal that. I run a pruning review once a quarter — spring is as good an anchor as any, because March is when you can see exactly what survived the winter and what didn't. Ninety minutes, the whole list, three possible verdicts per item: keep, kill, or park it (more on that below). The rule that makes it work is that pruning is a calendar event, not a courage event. Nobody has to work up the nerve to delete a senior person's pet idea in a random Tuesday meeting. The review deletes things. That's just what the review is for.

Give every item an expiration date

Here is the practice that does the heaviest lifting: an age limit. Any item older than a set threshold — I use twelve months for most lists, six for fast-moving ones — expires automatically unless someone re-argues for it. Not re-estimates it. Re-argues it: states, out loud or in writing, who it serves, what it costs to leave undone, and why now.

This sounds harsh until you watch it work. An item nobody will re-argue for was already decided. The team decided it the last fourteen times they picked something else. The backlog just hasn't admitted it yet. Expiration doesn't kill ideas — it forces the honest paperwork on decisions that have already happened. And sometimes the re-argument surprises you: someone makes the case, the room hears it fresh, and an old item legitimately jumps the queue. That's gardening too. Things come back into season.

A parking lot is not a warehouse

Every backlog needs a place for "not now," and this is where most teams cheat. A warehouse is indefinite: no owner, no date, no review — items go in and are never seen again. A parking lot, run properly, is deliberate. An item goes in with three things attached: a reason it isn't being done now, a date to look at it again, and a condition that would change the answer ("when the vendor contract renews," "when we hire the second tech," "if bookings hit the spring target"). When the date arrives, the item gets its hearing and one of the three verdicts. The difference is not the list. The difference is whether the list is a commitment or a landfill.

Saying no is a service

Auditors learn this early: a clean "no, and here's why" is kinder than an indefinite "we'll get to it." The requester whose idea sits in your warehouse for two years has planned around a maybe. They've told their own boss it's coming. They've skipped workarounds because the real fix is supposedly in line. A timely no lets them escalate, re-scope, build the workaround, or argue the case harder with better information. Silence dressed up as a backlog slot does none of that. Pruning is not disrespect for the requester. It is the first respectful thing you've done for them in months.

The pruning ritual

Here is the whole practice, small enough to run this week:

  1. Sort the list by age and look at the number. Count how many items are past your threshold. The count itself is diagnostic — if half your backlog is expired, you don't have a backlog, you have an archive.
  2. Hold the ninety-minute review. Owners present, requesters invited where practical. Every expired item gets a verdict: re-argued and kept (with today's reasoning written on it), parked (with a revisit date and a condition), or deleted.
  3. Delete in the meeting, in front of everyone. Not "we'll clean it up later." Later is where warehouses come from. Watching items actually leave the list is what rebuilds the team's belief that the list is real.
  4. Write the nos down. For every deleted request, send the requester two sentences: what was decided, and what would change it. Thirty seconds each, and it turns a silent burial into a service.
  5. Schedule the next pruning before you leave the room. Same quarterly rhythm, same threshold. A garden is not a project. It's a practice.

Do this four times and something shifts: the backlog gets shorter, the arguments get better, and the list starts meaning something again. Teams don't lose faith in backlogs because the work is hard. They lose faith because the list lies to them. Tend it like a garden — finite, pruned, and planted on purpose — and it will tell you the truth.

Monday, April 7, 2025

Prompt Injection Is the New SQL Injection

In the early 2000s, SQL injection was everywhere. Every web app built a query by smashing user input into a string, and attackers typed ' OR '1'='1 into login forms and walked right in. It was embarrassing, it was pervasive, and it took the industry the better part of a decade to dig out — mostly through parameterized queries and frameworks that made the safe thing the default.

Prompt injection is the same movie with a different cast.

The shape of the vulnerability is identical: untrusted input gets mixed into a trusted instruction stream, and the system can't tell which is which. Only now the "database" is a language model, the "query" is a prompt, and the "input" is whatever the user — or a webpage, or a document, or another agent — decided to feed it.

We've seen the demos. The résumé screener that gets told to ignore all other candidates. The support bot that gets jailbroken into handing out refund codes. The agent with access to your email that reads a phishing message and helpfully follows its instructions. Every one of these is the same bug wearing a new hat: the model treats data as instructions because nobody built a wall between them.

And here's the part that should worry you: we're repeating the timeline. SQL injection was a known, documented, exploited vulnerability for years while the industry shipped framework after framework that concatenated strings by default. Today we're shipping LLM features that concatenate prompts by default, and the security guidance is still mostly vibes.

So what does defense in depth actually look like for LLM apps? Not a single silver bullet — SQL injection didn't die because of one product, it died because of layers.

First: treat model output as untrusted. The model's answer is data, not a decision. If your agent can send email, move money, or change access, the model's output should be a *proposal* that something else validates — not a command that executes directly.

Second: least-privilege tool access. Your customer support bot does not need write access to the billing database. Your document summarizer does not need your inbox. Every tool you hand the model is an attack surface, and the model will use them exactly as creatively as an attacker tells it to.

Third: separate the channels. System instructions, user input, and retrieved content should be structurally distinct, and the model should be trained and configured to treat them that way. This is the parameterized-query equivalent — the thing that makes the safe path the default path. It's not perfect, and researchers keep finding bypasses, but it's the foundation everything else stacks on.

Fourth: filter the outputs, not just the inputs. Input filtering is a losing game — attackers are more creative than your blocklist. But you can validate what the model *produces* before it acts: does this response match the expected schema? Is this action within the allowed set? Is a human in the loop for anything consequential?

That last one deserves emphasis. The industry spent years trying to make the model itself the firewall — better alignment, better refusal training, better guardrails baked into the weights. That's like asking the database to sanitize its own queries. It helps, but it's not a security boundary. The boundary lives in your architecture, not in the model's mood.

The people building LLM features aren't careless. Most of them are moving fast on a platform that's genuinely new, and the security playbook is still being written. I get it. But the playbook has a first chapter, and we've already read it once.

We know how this story ends. The question is whether we spend another decade learning it.