The first 30 days on a GCP estate that has never had a platform engineer
What I actually do in the first month on a Google Cloud estate that grew without one — why I don't start with Terraform, why the billing console comes before the architecture diagram, and what has to be true before I leave.
Most of the Google Cloud estates I get called into were not built badly. They were built quickly, by people who had a product to ship and no one whose job was the layer underneath. Then they grew. Somewhere around the fifteenth Cloud Run service, the thing that used to be “we just deploy it” became a question nobody could answer in one sentence.
So somebody suggests hiring a platform engineer, and I turn up on a Monday.
What follows is what I actually do in the first month. It is not a methodology and it does not generalise to every estate — the order changes, and on one engagement I skipped most of week three because the thing that mattered was a billing problem nobody had noticed. But the shape holds, and the two decisions I get asked about most are both about what I don’t do first.
Week one: change nothing
The temptation on day one is to open an editor. Resist it for a week.
An estate that grew without a platform engineer is rarely uniformly bad. It is unevenly good — two services built carefully by someone who cared, six built in an afternoon under deadline, and one that everybody is slightly afraid of. The unevenness is the actual problem. If you start fixing before you can tell which is which, you will spend your best week rewriting the two careful ones, because they are the ones whose code you can read.
So the first week is inventory, and I start somewhere unglamorous.
Billing before architecture
The billing export is the fastest map of a system you have never seen, and it has a property no diagram has: nobody can forget to update it. Architecture docs go stale the week after they are written. A Cloud Billing export cannot, because it is generated from what is actually running and actually costing money.
Push it into BigQuery if it isn’t already, then group by service, by project, by SKU. Within an hour you will know things the team has not thought about in a year:
- Which projects exist at all. There is always one nobody mentioned.
- Which services cost real money and which round to zero. This is your priority order, and it is rarely the one you would have guessed.
- What is running that nobody uses. Idle Cloud SQL instances. A GKE cluster from an evaluation two years ago.
- Log retention somebody raised and nobody revisited. The default is thirty days. Someone hits a retention requirement, sets
_Defaultto a year, and it is free at the volume they had that week. Two years of growth later it is a line item nobody can explain, because the decision was correct when it was made and nothing re-examined it as the volume moved underneath it. - Whether anything is billed in a mode that does not match how it runs — a Cloud Run service on always-allocated CPU that serves forty requests a day is paying for a machine it does not need.
I have never done this exercise and not found something. The point is not the saving, though there usually is one and it is a pleasant thing to be able to report in week one. The point is that cost is a lens on architecture. An expensive line item is a place where the system is doing something, and if you cannot explain why it is expensive, you have found a thing you do not understand yet.
The question that tells you the most
Then I ask one question, and I ask it of an engineer rather than a lead:
If you joined on Monday, how long before you could get a change into production on your own?
The answer matters. The pause before the answer matters more. What you are listening for is whether the path exists and is written down, or whether it exists in one person’s head. Teams without a platform function almost always have the second, and almost always believe they have the first, because the person whose head it is has never needed to look it up.
I also read every incident write-up they have, if they have any. Not for the fixes — for the shape. Three incidents caused by the same class of thing is a structural problem wearing three different hats.
What I write down
By the end of week one I have one document, and it is deliberately boring: what runs, where, what it costs, who owns it, and how it gets deployed. No recommendations yet. Recommendations in week one are guesses with a confident font.
Week two: stop the bleeding
Now I fix things, but only one category: whatever will wake someone at three in the morning.
This is not the same as the ugliest thing. The ugliest thing is usually a service with bad naming and a 600-line handler that has run without incident for two years. Leave it. It is offensive, not dangerous.
What I am looking for in week two is the gap between “something broke” and “a human who can fix it knows about it”. In an estate with no platform function, that gap is usually enormous, and it is usually made of one of these:
Alerts that go nowhere. There is a monitoring policy, it has existed for eighteen months, and its notification channel is an email address belonging to someone who left. Or — more common and worse — the alerts work fine and there are four hundred of them a week, so everyone has filtered them into a folder. An alert nobody reads is not an alert, it is a log line with extra steps.
Jobs that fail silently. Scheduled work is where this lives. A nightly job that exits non-zero and tells nobody will run broken for months. The cheapest fix in all of platform engineering is a heartbeat: the job reports that it completed, and an alert fires when the report does not arrive. That is a different thing from alerting on failure, and it is the one that catches the job that stopped running entirely.
No way to tell what a request did. If a customer reports something odd at 14:20 and the only way to investigate is grepping unstructured logs across six services, every incident costs hours it should not. Trace-correlated logging — a trace ID that follows a request and appears on every line it produces — turns that into a query. This is not a rewrite; it is usually a logging library and a header.
Standing access. Someone has Owner on production. Frequently several someones, sometimes a service account with a JSON key that has been in a CI variable since 2023. I do not fix this properly in week two — that is a project. But I find out and I write it down, because it changes what else is safe to do.
I fix these in the order of how likely they are to matter, not how hard they are. And I fix them in place, in the estate as it exists, with no prerequisite refactor. The point of week two is that the team is measurably safer at the end of it than at the start, before I have asked them to change how they work at all.
Week three: the first slice of a landing zone
Only now do I open Terraform. Or Pulumi — I will come back to that in another piece, because the choice matters less than the thing people get wrong about both.
Here is the position that gets me the most argument, from an infrastructure-as-code person: do not import your existing estate into code as a first step. I have watched teams spend two months on this and end up worse off. What you get is a faithful, thousand-resource representation of a mess you had not understood yet, which now sits between you and every change. You have not made anything better. You have made it slower to make it better, and you have taught everyone that the IaC repo is where changes go to die in review.
Infrastructure as code is a mechanism for making decisions durable. In week three you have finally made some. Encode those.
What that means concretely: the first slice is the organisation layer, not the workload layer. Project structure and the rules about what a project is for. The IAM that follows from the access audit in week two. Org policy constraints — the handful that would have prevented the things you found. A service account per workload with the permissions it actually uses. The alerting that week two proved was necessary, now expressed as code so it cannot be deleted by someone tidying a console.
That is a small amount of code. It should be. It is reviewable, it encodes decisions somebody can defend, and the existing services keep running exactly as they were while it lands. Then workloads migrate into it one at a time, on their own schedule, and each migration is a small change with a small blast radius instead of a big-bang cutover nobody wants to be on call for.
The other half of week three is the thing that makes the rest of it stick: a way to get a new service that is correct by default. Whatever shape it takes in your stack — a module, a component, a template — the property that matters is that a team asking for a new service gets observability, cost controls, IAM and secrets without asking for them, and without knowing they exist. Platform work fails when doing the right thing requires remembering to. Make the default correct and the documentation becomes a nice-to-have rather than the only thing standing between you and an incident.
Week four: make yourself unnecessary
I have been hired because the team could not do something. The engagement has failed if that is still true when I leave.
So week four is deliberately not building. It is:
Writing down the decisions and why. Not documentation of how things work — code shows how things work, and prose about it goes stale immediately. Decision records: what we chose, what we rejected, and what would have to change for the decision to be wrong. That last clause is the one people skip and the one that pays. Six months later somebody asks “why don’t we just —” and the answer already exists, along with the conditions under which they would be right.
A runbook for each thing that can page someone. Not a wiki. A short, specific document per alert: what it means, how to confirm it, what to do, and who to escalate to if that does not work. If an alert has no runbook, either write one or delete the alert, because an alert that arrives at 3am with no instructions is a wake-up call with no purpose.
Watching someone else do it. The real test. Pick a change, hand it to an engineer on the team, and sit on your hands. Everything they get stuck on is a gap in what you built, and you have a week to close it. This is uncomfortable and it is the most valuable day of the month.
What “done” looks like
Thirty days does not produce a finished platform. What it should produce is:
- An inventory of what actually runs and what it costs, derived from billing rather than memory.
- A meaningfully shorter path between something breaking and a human who can fix it knowing about it.
- A landing zone with the organisation layer in code and workloads migrating into it at their own pace.
- A default path for new services that is correct without anyone remembering to make it so.
- Decision records and runbooks, so the next person does not have to reconstruct the reasoning.
- At least one engineer on the team who has made a change through the new path with nobody helping.
That last one is the only item I would refuse to drop. Everything else is infrastructure, and infrastructure that only one person understands is not a platform — it is a dependency, and I am it.
If you are about to do this on your own estate, the piece of advice I would most want you to take is the boring one: spend the first week finding out, and resist the editor. Everything after it gets cheaper.
FAQ
Why not start with Terraform?
Because importing an estate you do not understand yet produces a Terraform configuration you do not understand either, and now every change has to pass through it. Infrastructure as code is a way to make decisions durable. You have not made any decisions yet. Spend the first weeks finding out what the decisions should be, and the code that follows is short, deliberate and worth reviewing.
What if the team says everything is fine?
They are usually right that it works, and that is not the same claim. "Nothing is on fire" and "we can change this safely" are different properties, and teams without a platform function tend to have the first and not the second. Ask how long it takes a new engineer to deploy something to production on their first day. The number, and the pause before you get it, tells you more than an architecture review.
Is 30 days enough to fix an estate?
No, and it is not meant to be. Thirty days is enough to know what is actually running, to close whatever will page someone at three in the morning, and to have the first slice of a landing zone that later work can build on. Anyone promising a finished platform in a month is describing a template, not your estate.