A GCP project and service account migration with zero downtime sounds like a slide title until you are the one holding the audit. On day one I opened the service account inventory and counted 99 accounts spread across eight projects. Most had never been reviewed. Some carried owner-level access granted years earlier by people who had long since left. Nobody in the room could tell me which ones were still in use.
That was the easy part.
The real mandate: move eight GCP projects from a legacy organizational tenant to a governed one, across two organizations, without breaking a single deployment. The dev team shipped multiple times a day and loved their autonomy. Leadership needed governance, compliance, naming standards, and billing controls. My job was to deliver both without making the developers hate me.
What we inherited
The legacy tenant was what happens when a platform grows faster than anyone can document it:
- 99 service accounts, most never audited, many over-privileged
- Owner-level roles left over from years-old one-off tasks
- No naming conventions and no org policies
- Projects scattered across folders with no clear ownership
- Cross-project network dependencies and MySQL tunnels nobody had written down
The developers liked it that way, because autonomy felt fast. Leadership saw an unaudited attack surface with a compliance deadline attached. Both were right.
The phased approach: smallest blast radius first
I did not try to move everything at once. I started with the dev project. Smallest blast radius. If the migration path was wrong, I wanted to find out there and not in production.
It worked, so the plan hardened into phases:
- Dev project to validate the migration path end to end.
- Five production workloads with cross-domain access requirements, MySQL tunnels, and undocumented network dependencies.
- The analytics and dashboard data layer, where the reporting lived.
- Onboarding everything into the secure tenant with strict org policies, naming standards, and full compliance.
Each phase taught me something I applied to the next. By the time the production workloads moved, I already knew where the sharp edges were.
The scariest part: surgical IAM hardening
Cleaning up 99 service accounts without breaking production is the kind of work that keeps you at the keyboard past midnight. Every account could break something, and there was no map.
So I treated each one as a small investigation before touching it:
- Some existed for services that had been decommissioned two years earlier.
- Some held permissions for projects that no longer existed.
- Some were actively used by pipelines that ran every single hour.
The rule I gave myself was simple: understand what an account actually does before removing anything. Right-size, do not guess. A single wrong revocation and a production tenant goes dark. Service accounts are the quiet attack surface nobody thinks about until an audit forces them to, and this audit had teeth.
CI/CD: autonomy with guardrails
A team that deploys multiple times a day cannot be slowed down, so the pipeline design had to give developers autonomy while enforcing security guardrails by default. The trick was to make the compliant path the easy path.
Developers kept their velocity. They just stopped deploying through artisanal scripts and started deploying through standardized pipelines that carried the guardrails inside them. Nobody had to remember to be compliant, because the pipeline already was.
The network nobody documented
The least glamorous risk was the network. Cross-project dependencies, shared connectivity, and MySQL tunnels all had to survive the move intact. These were the things not written down anywhere, discovered only by tracing what actually talked to what. Every one of them had to keep working the moment a project landed in the new tenant.
The outcome
Eight projects migrated. Zero downtime. Deployment frequency unchanged. The team still pushes multiple times a day, they just do it through governed pipelines now. The 99 service accounts became a right-sized, documented, policy-compliant set, and the whole platform lives in a tenant that passes an audit instead of dreading one.
Governance without friction
Here is the lesson I keep coming back to. Governance that slows teams down is not governance. It is bureaucracy wearing a compliance badge. The only governance that survives at global scale is the kind developers barely notice because the safe path is also the fast path.
Ninety-nine service accounts, and not one person could explain what half of them did. If that sounds familiar, the orphaned accounts sitting in your projects right now are not waiting for your convenience. They are waiting for your next audit.