Home Resume
Home Blog GCP Architecture Series #6 — Deleting a Project: The Undo Button That Only Half Works…
GCP Architecture GCP Architecture Series

GCP Architecture Series #6 — Deleting a Project: The Undo Button That Only Half Works

A team deletes a project believing the 30-day recovery window makes the decision reversible, and discovers on restoring it that the window protects the project record rather than its contents — some services remove data much sooner — while the project has been unusable since the moment it was marked and has been consuming project quota the whole time.

Verified against current vendor documentation on 19 August 2026. Pricing, limits and API behaviour were checked against the official docs on that date. Cloud services change fast — if you are reading this much later, treat the specifics as a starting point and re-check the linked sources.

Business Challenge

A platform team is retiring an old data pipeline. The project is clearly dead — no deployments in eight months, no traffic — and somebody has read that deletion is reversible for thirty days. That fact does most of the persuading, and the project is deleted on a Tuesday.

1
A dashboard broke within the hour

Deleting does not begin a countdown during which things keep working. The project is marked for deletion immediately and becomes unusable from that moment, so anything still calling it fails at once rather than in thirty days.

Correct approach

Treat the delete call as the outage, not the end of the window. If you need a soak period, stop using the project and leave it running; deletion is not a staged rollout.

2
The restore returned an empty project

Restoring on day nine brought the project back, and some of what had been inside it was gone. Google documents that some services, naming Cloud Storage and Pub/Sub, might delete resources much sooner than the 30 day window.

Correct approach

Read the window as protecting the project record, not its contents. Anything you would genuinely need back must be backed up or exported before the delete call, not after it.

3
Deleting projects did not free up room for new ones

Soft-deleted projects count against your quota and are only fully deleted after 30 days. A clear-out done to make space makes no space at all until the following month.

Correct approach

Plan quota on a thirty-day lag, and request an increase ahead of a migration rather than deleting your way out of a limit on the day.

4
The replacement project could not have the old name

Project IDs are unique and permanent, and once a project is fully deleted its ID cannot be reused. The rebuild had to be given a slightly different ID, which now differs from every runbook, dashboard and bookmark that referenced the original.

Correct approach

If a project is being rebuilt rather than retired, build the replacement first under its own ID and migrate. Deleting to reclaim a name does not reclaim it.

Every one of those is documented behaviour. None of it contradicts "you have thirty days to restore it" — they are all things that sentence does not say.

Two clocks, and only one of them is thirty days

The project record is restorable for the full window by an owner. The data inside it runs on whatever schedule each service chooses, and at least two services are documented as being much faster. A recovery plan that assumes both clocks are the same is relying on a guarantee Google explicitly declined to make.

Architecture

The lifecycle has two states worth naming and one transition that is genuinely irreversible.

Diagram: the project lifecycle from ACTIVE through DELETE_REQUESTED to permanent deletion, with the 30-day restore window for the project record drawn against the shorter and undefined window for data in services like Cloud Storage and Pub/Sub
Two clocks running at once. The project is restorable for thirty days; the contents run on each service's own schedule.

What happens the instant you call delete

The project is immediately marked for deletion and becomes unusable, entering DELETE_REQUESTED. There is no grace period during which it keeps serving. Whatever still depends on it starts failing straight away.

This is the single most misread part of the lifecycle, because "you have thirty days" sounds like thirty days of continued operation. It is thirty days of being able to undo, which is a different offer entirely.

What the thirty days actually cover

The project remains in DELETE_REQUESTED for 30 days, and during that period project owners can restore it. After the window, the project and all its resources are permanently deleted.

The qualifier that matters sits right next to it: some services, such as Cloud Storage and Pub/Sub, might delete resources much sooner. So the honest reading is that the platform guarantees the project can come back, and makes no equivalent promise about everything that was in it. Restoring on day twenty-nine is not the same operation as restoring on day one, and neither is guaranteed to be lossless.

This is also why post #3's phrase — DELETE_REQUESTED is "generally reversible" — is worded as carefully as it is. The reversibility is real and it is not total.

The two permissions, and why they are separate

Deletion requires resourcemanager.projects.delete. Restoration requires resourcemanager.projects.undelete. They are distinct permissions, which means the ability to undo is a grant somebody has to hold deliberately.

Worth checking before you need it. A team that can delete projects but has nobody holding undelete has a one-way door it believes is a revolving one, and it will find that out under time pressure.

Quota does not come back until the end

Soft-deleted projects count against your quota, and are fully deleted after 30 days. Deleting projects to make room for new ones therefore does nothing for a month.

Combined with the advice from earlier posts — a project per workload per environment — this is a real planning constraint rather than trivia. The design that makes the best use of projects is also the one most likely to meet the limit, and the relief valve has a thirty-day delay in front of it.

Why This Architecture Holds Up

There is an undo button. The argument of this post is that you should design as though there is not, and the reasoning is about which failures the window actually protects you from.

It protects against the wrong project being deleted — somebody typing the wrong ID, a script iterating one item too far. That failure is caught in minutes, well inside any service's cleanup schedule, and the restore genuinely works.

It does not reliably protect against the wrong decision. That is the failure discovered weeks later, when somebody asks for a report that turns out to have been generated from a bucket in a project that was retired. By then the project may restore and the bucket may not, because the data was on a different clock from the moment the delete was called.

The one-sentence version to give a team

Deleting a project stops it working immediately, might destroy some of its data long before the thirty days are up, keeps consuming your project quota until the window closes, and permanently burns the project ID. The undo button covers the container, not the contents.

Liens are the control that fits this shape

Post #3 covered liens as a brake on deletion, and this is where their value becomes concrete. A lien blocks a project's deletion until it is removed, which converts an irreversible action into one that requires a deliberate second step by somebody holding a different permission.

Given everything above, the argument for putting liens on production projects is not that deletion is hard to undo. It is that the undo is only partial, so the cheapest place to intervene is before the delete call rather than after it.

A retirement sequence that survives being wrong

Because the window is weaker than it appears, the order of operations does the work instead:

  • Stop using it, and leave it running. This is the soak period people imagine deletion gives them, and it is the only version that actually exists. Anything still calling the project surfaces here rather than after the point of no return.
  • Export or back up anything of value. Before the delete call, because after it the data is on a schedule you do not control and cannot query.
  • Remove the lien deliberately, as a separate, recorded step.
  • Delete, and treat the ID as spent. Not recoverable, not reusable, and not worth planning to reclaim.

Key Architecture Decisions

DecisionChoose thisBecause
How to treat the 30-day window As protection against the wrong project, not the wrong decision It reliably reverses a mistyped ID caught in minutes. It does not reliably return data, because some services delete much sooner.
Backing up before retirement Export before the delete call, always After it the project is unusable and its data is on each service's own cleanup schedule, which you cannot inspect or postpone.
Wanting a soak period Stop using the project and leave it running Deletion is immediate and total in effect from the first second. It is not a staged rollout with a thirty-day tail.
Who can restore Grant resourcemanager.projects.undelete deliberately, and check it before you need it It is a separate permission from delete. A team that can only delete has a one-way door it believes is reversible.
Production projects A lien The undo is partial, so the effective place to intervene is before the delete call rather than after it.
Deleting to reclaim quota Do not — request an increase instead Soft-deleted projects keep consuming quota for the full 30 days, so a clear-out frees nothing this month.
Deleting to reclaim a project ID Never The ID cannot be reused once the project is fully deleted. Rebuild under a new ID and migrate.
Scripted clean-ups Dry-run, and require an explicit list rather than a filter The window makes a mistyped ID recoverable, but only if somebody notices quickly. A filter that matches one project too many is discovered late by definition.
What "generally reversible" is careful not to say

The API documentation describes DELETE_REQUESTED as generally reversible, and the deletion guide names Cloud Storage and Pub/Sub as services that might remove resources much sooner. Those two statements are consistent, and together they mean the project comes back while its contents are a matter of timing and of which services it used.

Closing Thought

Deletion is where the difference between a documented guarantee and an assumed one gets expensive. Google promises the project record can be restored for thirty days, states plainly that some services will not wait that long, and lets those two facts sit side by side because both are true.

The mistake is not misreading either sentence. It is hearing "thirty-day recovery" and filing it as "reversible", then designing a retirement process on that word. Everything in this post follows from separating the container from the contents, and the practical consequence is small: back up before you delete, and stop treating the window as permission to skip that step.

Next in this series

#7 takes liens on their own terms: what they block, the separate role required to remove one, why that separation is the point rather than an inconvenience, and where they belong in an estate that is otherwise governed by organization policy.

Comments

How was your experience?
Your feedback helps improve this site.
PoorExcellent