Object Lifecycle Management in GCP: Automate Storage Class Transitions and Deletion
Without lifecycle rules, objects accumulate in your buckets indefinitely and storage costs grow unchecked. Object lifecycle management lets you define rules that automatically delete objects or move them to cheaper storage classes when conditions are met. No cron jobs. No manual cleanup scripts. No remembering to run a delete command six months from now.
What object lifecycle management is in plain terms
A lifecycle policy is a set of rules you attach to a Cloud Storage bucket. Each rule says: when an object in this bucket meets these conditions, do this action.
The conditions might be: the object is older than 30 days, its name starts
with logs/, or it is a noncurrent version in a versioned bucket.
The action is either delete the object or move it to a cheaper
storage class.
Cloud Storage evaluates these rules once per day. When an object satisfies the conditions in a rule, the action runs automatically.
Think of a bucket as a mail room. Lifecycle rules are the standing instructions pinned to the wall: “anything in the incoming tray for more than 30 days, move to the slow archive shelf; still there after 90 days, move it off-site; after a year, shred it.” Staff follow those instructions every morning without being told. You write the rules once and then stop thinking about the mail room.
Why lifecycle management matters
Most buckets hold data with a natural expiry. Application logs are useful for debugging for a week and relevant for trend analysis for 90 days. After that they just occupy storage. Database backups should be kept for 30 days then discarded. Build artefacts from a CI pipeline rarely outlive the sprint they were built for.
The teams that get storage costs under control set up lifecycle rules at bucket creation time, not six months later when the bill has grown.
- Lower storage costs: automated transitions to Nearline, Coldline, or Archive reduce per-GB monthly charges for data you rarely access.
- Cleaner buckets: old exports, temporary uploads, and stale artefacts do not accumulate indefinitely.
- No manual cleanup: you define the intent once; Cloud Storage handles execution every day.
- Safer than scripts: a well-tested lifecycle rule is declarative and auditable. A misconfigured cron job can delete the wrong objects entirely.
How object lifecycle management works
Here is the basic flow from policy to execution:
- You write a lifecycle policy as a JSON document and attach it to a bucket.
- The policy contains one or more rules. Each rule has a condition and an action.
- Once per day, Cloud Storage evaluates every object in the bucket against each rule.
- If an object satisfies all conditions in a rule, Cloud Storage runs the action.
- Changes take effect within 24 hours. Execution is not immediate.
A few things to know before you write your first policy:
- Rules apply at the bucket level. You can target different prefixes within a bucket using the
matchesPrefixcondition, but the policy itself is attached to the bucket. - If you add a rule today and objects already meet the condition, they may be acted on in the next daily evaluation cycle.
Lifecycle rules interact closely with object versioning and storage classes. Effective lifecycle policies always account for all three.
Apply lifecycle rules when you create a bucket, not weeks later. Storage cost problems are nearly always discovered in retrospect. A single well-placed rule at bucket creation time is worth more than a cleanup effort after six months of accumulation.
Lifecycle rule structure
Each rule has exactly two parts:
- Condition — the criteria an object must satisfy for the rule to fire. You can combine multiple conditions; all must be true.
- Action — what happens when the condition is met: delete the object or move it to a different storage class.
The policy is a JSON document with a lifecycle key containing a
rule array. Here is the skeleton:
{
"lifecycle": {
"rule": [
{
"condition": { "age": 30 },
"action": { "type": "SetStorageClass", "storageClass": "NEARLINE" }
},
{
"condition": { "age": 365 },
"action": { "type": "Delete" }
}
]
}
}Available conditions
You can combine multiple conditions in a single rule. All conditions must be true for the action to apply.
age: the number of days the object has existed. For live objects, this is days since creation. For noncurrent versions in versioned buckets, it is days since the version became noncurrent. This is the most commonly used condition.
Use case: delete log files older than 365 days.createdBefore: matches objects created before a specific date in ISO 8601 format, for example2025-01-01.
Use case: one-off cleanup of objects created before a data migration.storageClass: matches objects currently in a specific storage class. Use this to chain transitions cleanly.
Use case: transition to Coldline only objects already sitting in Nearline.isLive:truefor live (current) versions,falsefor noncurrent versions. Only meaningful when versioning is enabled.
Use case: permanently delete noncurrent versions after 90 days without affecting live objects.numNewerVersions: the number of newer versions of the same object that must exist before this rule applies.
Use case: delete older noncurrent versions once three newer versions of the file exist.matchesPrefix/matchesSuffix: limits the rule to objects whose names start or end with a specific string.
Use case: delete objects undertmp/after 7 days while leaving everything else alone.customTimeBefore: matches objects whose custom time metadata is before a given date. Lets your application drive lifecycle behaviour using a date it writes to object metadata, rather than the object creation time.
Use case: expire data based on a publish date your application sets at upload time.
Available actions
Delete— removes the object permanently.SetStorageClass— transitions the object to a different storage class. Valid targets areNEARLINE,COLDLINE,ARCHIVE, andSTANDARD.
In a versioned bucket, applying Delete to a live object without specifying
isLive: false creates a delete marker rather than permanently
removing it. The object becomes noncurrent and keeps accumulating charges.
To permanently remove noncurrent versions, write a separate rule with
isLive: false.
Each storage class has a minimum storage duration: Nearline is 30 days, Coldline is 90 days, Archive is 365 days. If you transition or delete an object before that minimum elapses, you are charged for the remaining days. Design transitions so each stage lasts at least as long as the current class minimum before you move on.
A simple first example
Before looking at a full multi-stage policy, here is the simplest useful rule:
delete objects in the tmp/ prefix after 7 days. This is the
standard pattern for temporary upload staging areas.
{
"lifecycle": {
"rule": [
{
"condition": {
"age": 7,
"matchesPrefix": ["tmp/"]
},
"action": {
"type": "Delete"
}
}
]
}
}# Save the policy to a file, then apply it to a bucket
gcloud storage buckets update gs://my-app-uploads \
--lifecycle-file=lifecycle-policy.json
# Confirm the policy is attached
gcloud storage buckets describe gs://my-app-uploads \
--format="json(lifecycle)"Objects outside the tmp/ prefix are not affected. This single
rule keeps a staging bucket clean without any application-side cleanup logic.
A realistic example: three-stage log retention
A common production pattern is to move log files through multiple storage classes as they age, then delete them after one year. This balances accessibility for recent logs against cost for older ones.
{
"lifecycle": {
"rule": [
{
"condition": {
"age": 30,
"matchesPrefix": ["logs/"]
},
"action": {
"type": "SetStorageClass",
"storageClass": "NEARLINE"
}
},
{
"condition": {
"age": 90,
"matchesPrefix": ["logs/"],
"storageClass": "NEARLINE"
},
"action": {
"type": "SetStorageClass",
"storageClass": "COLDLINE"
}
},
{
"condition": {
"age": 365,
"matchesPrefix": ["logs/"]
},
"action": {
"type": "Delete"
}
}
]
}
}# Apply the policy to a bucket
gcloud storage buckets update gs://my-app-logs \
--lifecycle-file=lifecycle-policy.json
# Remove all lifecycle rules from a bucket
gcloud storage buckets update gs://my-app-logs \
--clear-lifecycleRule one moves log files to Nearline after 30 days. Rule two moves them to
Coldline once they are 90 days old and already in Nearline. Rule three deletes
anything in logs/ after one year.
The storageClass: NEARLINE condition in rule two matters. Without
it, both the Nearline and Coldline rules could match the same object on the same
evaluation day, and Cloud Storage would apply the lowest-cost class (Coldline),
skipping Nearline entirely.
When chaining class transitions, include the storageClass
condition in intermediate rules. This prevents multiple rules from competing
on the same object and ensures each stage is reached in sequence.
Lifecycle rules for versioned buckets
When versioning is enabled on a bucket, every overwrite or deletion creates a noncurrent version rather than removing the previous content. This protects against accidental data loss, but every noncurrent version is billed at the same rate as a live object.
For versioned buckets, you typically need two sets of rules: one for live objects and one for noncurrent versions. Omitting noncurrent version rules is the most common and costly oversight when using versioning.
{
"lifecycle": {
"rule": [
{
"condition": {
"numNewerVersions": 3,
"isLive": false
},
"action": {
"type": "Delete"
}
},
{
"condition": {
"age": 7,
"isLive": false
},
"action": {
"type": "SetStorageClass",
"storageClass": "NEARLINE"
}
},
{
"condition": {
"age": 90,
"isLive": false
},
"action": {
"type": "Delete"
}
}
]
}
}The first rule deletes a noncurrent version once three newer versions of the same object already exist. The second moves noncurrent versions to Nearline after 7 days to reduce cost while keeping them accessible for recovery. The third permanently deletes any noncurrent version after 90 days regardless of how many newer versions exist.
All three rules use isLive: false so they only apply to noncurrent
versions and leave live objects unaffected.
Every noncurrent version is billed at full storage rates. If you enable versioning on an active bucket and never add cleanup rules, costs will grow silently in proportion to how often objects are overwritten. Always pair versioning with at least one noncurrent version cleanup rule.
When to use lifecycle rules
Lifecycle rules are the right tool whenever data in a bucket has a predictable retention pattern. Common scenarios:
Application logs. Keep recent logs in Standard for debugging, move to Nearline after 30 days, Coldline after 90, delete after a year. This is the canonical use case.
Temporary uploads. Users upload files for processing. Once processed, the originals are no longer needed. A prefix-based Delete rule removes them after a few days without any application-side cleanup code.
CI/CD artefacts. Build outputs, test results, and packaged releases from a pipeline have no value after the sprint. A 30-day deletion rule keeps the bucket manageable.
Database backups. Keep the last 30 days of backups accessible in Nearline, then delete. If you also use backup and high-availability strategies, lifecycle rules are a key part of controlling cost over time.
Old data exports. One-off exports created for a migration or audit become obsolete once the project finishes. A
createdBeforecondition or an age-based Delete rule handles the cleanup.Versioned bucket hygiene. Any versioned bucket without noncurrent version lifecycle rules will grow in storage cost indefinitely. Lifecycle rules are the standard mechanism for controlling this.
Lifecycle rules vs retention policies
These two features are often confused because both involve how long objects stay in a bucket. They work in opposite directions and solve different problems.
Lifecycle rules delete or transition objects when conditions are met. They are about automation and cost control.
Retention policies prevent objects from being deleted before a minimum period has elapsed. They protect against premature deletion and are used for compliance and legal hold requirements.
| Feature | Lifecycle rules | Retention policies |
|---|---|---|
| Purpose | Automate deletion and class transitions | Prevent deletion before a minimum period |
| Direction | Encourages cleanup | Enforces retention |
| Configured at | Bucket level as a JSON policy | Bucket level as a retention period |
| Typical use | Log cleanup, backup expiry, cost control | Compliance records, legal holds, audits |
| Can coexist? | Yes — both can apply to the same bucket | |
A practical example: a compliance bucket might have a 7-year retention policy (preventing deletion before 7 years) alongside a lifecycle rule that moves objects to Archive after 90 days (reducing cost while they are retained). The lifecycle rule handles cost; the retention policy handles the compliance requirement.
If a lifecycle Delete rule and a retention policy conflict — the rule would delete an object before the retention period expires — the retention policy wins. Cloud Storage will not delete an object still within its retention period.
Lifecycle rules and retention policies are complementary, not alternatives. Use lifecycle rules for cost management and retention policies for compliance. On regulated buckets you often need both.
For more on data protection controls, see Cloud Storage Security.
Common mistakes
Enabling versioning without lifecycle rules for noncurrent versions. Versioning is genuinely useful, but without cleanup rules for old versions, every overwrite silently creates a new billable copy. Costs grow in the background for months before anyone notices. Always pair versioning with at least one noncurrent version cleanup rule.
Writing rules that conflict with each other. A rule that deletes objects at 30 days and another that moves them to Coldline at 60 days means the Delete fires first and the transition never happens. Review your rules as a set, not individually, and test on a non-production bucket.
Expecting lifecycle rules to run immediately. Rules are evaluated once per day. An object that becomes eligible today may not be acted on until tomorrow. Do not use lifecycle rules as a substitute for anything that needs precise timing.
Ignoring minimum storage duration when chaining transitions. Moving an object from Coldline (90-day minimum) to Archive at day 50 still charges you for the remaining 40 days of Coldline minimum storage. Design your chain so each stage lasts at least as long as that class’s minimum duration before transitioning out of it.
Confusing lifecycle rules with retention policies. Lifecycle rules cause deletion; retention policies prevent it. If you add a lifecycle Delete rule to a bucket that has a retention policy, the retention policy takes precedence during the retention period.
Best practices
Start simple. One or two clear rules are easier to reason about than a complex policy with many overlapping conditions. Add complexity only when a simpler rule cannot capture your intent.
Test on a non-production bucket first. Upload representative objects, apply the lifecycle policy, and verify expected behaviour before rolling it out to production.
Use prefixes to separate policies by data type. A single bucket can hold logs, uploads, and exports with different rules per prefix. This avoids needing separate buckets purely for lifecycle reasons.
Check minimum durations before designing transitions. Know the minimums (Nearline: 30 days, Coldline: 90 days, Archive: 365 days) before choosing transition ages. Rushing a transition incurs early deletion fees that erase the cost savings.
Document the retention intent. Add a comment in your infrastructure code or a README alongside the lifecycle policy file explaining why each retention period was chosen. Future reviewers and auditors will need that context.
Revisit policies as data patterns change. Review lifecycle policies periodically and adjust transition ages to match actual access frequency, which you can check in Cloud Storage usage metrics.
Summary
- A lifecycle policy is a JSON document attached to a bucket, containing condition-action rules evaluated once per day
- Conditions include
age,createdBefore,storageClass,isLive,numNewerVersions,matchesPrefix,matchesSuffix, andcustomTimeBefore - Actions are
Delete(permanent removal) orSetStorageClass(transitions to Nearline, Coldline, Archive, or Standard) - On versioned buckets, write separate rules for live objects and noncurrent versions; omitting noncurrent rules is the most common mistake
- Rules take effect within 24 hours, not immediately
- When chaining transitions, use the
storageClasscondition in intermediate rules to prevent rules competing on the same object - Respect minimum storage durations (Nearline: 30 days, Coldline: 90 days, Archive: 365 days) to avoid early deletion fees
- Lifecycle rules automate deletion; retention policies prevent it. They solve different problems and can coexist on the same bucket
Frequently asked questions
How long does a lifecycle rule take to apply?
Lifecycle rules are evaluated once per day. Changes you make to a policy typically take effect within 24 hours, but Google does not guarantee a specific time. An object that becomes eligible for deletion or transition today may not be acted on until tomorrow. Do not rely on lifecycle rules for anything that requires precise timing — they are designed for background cleanup, not real-time automation.
Can a lifecycle rule delete objects in a versioned bucket?
Yes, but you need separate rules for live objects and noncurrent versions. Applying a Delete action to a live object in a versioned bucket creates a delete marker rather than permanently removing it — the object becomes noncurrent and continues to occupy storage. To permanently delete noncurrent versions, add a rule with isLive: false and an age or numNewerVersions condition. This is the most common oversight when setting up lifecycle rules on versioned buckets.
What is the difference between lifecycle rules and retention policies?
Lifecycle rules automatically delete or transition objects when conditions you define are met — they are about automation and cost control. Retention policies do the opposite: they prevent objects from being deleted before a minimum retention period has elapsed. They solve different problems. Lifecycle rules reduce storage costs by cleaning up old data. Retention policies enforce compliance by preventing premature deletion. You can apply both to the same bucket, and if they conflict, the retention policy takes precedence.
Can I target only some objects in a bucket with a lifecycle rule?
Yes. Use the matchesPrefix or matchesSuffix conditions to limit a rule to objects whose names start or end with a specific string. For example, matchesPrefix: ["logs/"] applies the rule only to objects in the logs/ prefix. You can also use the storageClass condition to target only objects in a specific class, or combine multiple conditions so that all must be true before the rule fires.
What happens when multiple lifecycle rules match the same object?
Cloud Storage evaluates all matching rules and applies the highest-precedence action. Delete takes precedence over SetStorageClass. If multiple SetStorageClass rules match, Cloud Storage applies the transition to the lowest-cost storage class. To avoid unexpected behaviour, design your rule sets so rules do not conflict. Simpler, non-overlapping rules are much easier to reason about and test.