Managing Cloud Storage and Databases: Lifecycle, Backups, and CMEK
Managing storage and data solutions on Google Cloud comes down to four operational skills: securing Cloud Storage objects (uniform bucket-level access with IAM, signed URLs for temporary sharing, versioning for recovery), automating cost with object lifecycle policies that transition or delete objects by age and state, protecting databases with the right backup mechanism (Cloud SQL automated backups plus point-in-time recovery, and the equivalent features in Spanner, Firestore, AlloyDB, and Bigtable), and controlling encryption with customer-managed encryption keys (CMEK) in Cloud KMS. Around those sit the daily tasks: querying each data service with its native tool — gcloud sql connect, bq, cbt, gcloud spanner — checking Dataflow and BigQuery job status, estimating storage costs across classes, and watching the whole database fleet from Database Center. This lesson covers each task the way the exam frames it: pick the mechanism, know the command, and avoid the cost and security gotchas.
On this page8 sections
- Securing objects in Cloud Storage: IAM, ACLs, and signed URLs
- Object lifecycle management policies
- Executing queries against your data services
- Estimating the cost of data storage
- Backing up and restoring database instances
- Reviewing job status: Dataflow and BigQuery
- Managing the database fleet with Database Center
- Configuring customer-managed encryption keys (CMEK)
- Secure Cloud Storage objects by choosing between uniform bucket-level access with IAM and fine-grained ACLs, and share objects safely with signed URLs
- Write object lifecycle rules that transition objects across storage classes and delete stale or noncurrent versions
- Query each managed data service with its native tool: gcloud sql connect, bq, cbt, gcloud spanner, and the Firestore and AlloyDB clients
- Configure backups and point-in-time recovery for Cloud SQL, and identify the backup mechanisms for Spanner, Firestore, AlloyDB, and Bigtable
- Review Dataflow and BigQuery job status from the console, gcloud, and bq
- Configure customer-managed encryption keys (CMEK) with Cloud KMS, including the service agent key grant
Securing objects in Cloud Storage: IAM, ACLs, and signed URLs
You secure Cloud Storage objects with IAM at the bucket level, and you should almost always enable uniform bucket-level access, which disables per-object ACLs so IAM policies alone govern the bucket. That gives you one consistent, auditable permission model. The legacy alternative, fine-grained access, lets each object carry its own ACL — needed only for rare per-object permission schemes, and a source of accidental exposure otherwise. Grant access with roles such as roles/storage.objectViewer (read objects), roles/storage.objectAdmin (full object control), and roles/storage.admin (buckets and objects), for example: gcloud storage buckets add-iam-policy-binding gs://BUCKET_NAME --member=user:ana@example.com --role=roles/storage.objectViewer. Turn on public access prevention to make it impossible to grant access to allUsers, and note that gsutil-era workflows are now handled by the gcloud storage command group.
To give someone temporary access without a Google account or any IAM change, generate a signed URL: a time-limited URL cryptographically signed with a service account's credentials that grants access to exactly one object until it expires, for example gcloud storage sign-url gs://BUCKET_NAME/report.pdf --duration=1h --private-key-file=key.json. Whenever a question says an external user, a mobile app, or a partner needs short-lived access to a single object, the answer is a signed URL — not making the bucket public and not creating IAM bindings.
Object versioning protects against overwrites and deletions: once enabled on a bucket, replacing or deleting an object turns the old data into a noncurrent version you can list (gcloud storage ls --all-versions) and restore by copying back. Versioning multiplies storage cost if you never clean up, which is exactly what lifecycle rules are for — the next section. For compliance holds where even admins must not delete data, use bucket retention policies or Object Lock features rather than versioning.
Object lifecycle management policies
A lifecycle policy automates cost control: each rule pairs one action with one or more conditions, and Cloud Storage applies the action when every condition on a rule is true. The two main actions are SetStorageClass (transition the object to a colder class) and Delete (remove it, or remove a noncurrent version); AbortIncompleteMultipartUpload cleans up abandoned uploads.
| Condition | Matches when | Typical use |
|---|---|---|
age | Object is older than N days | Move logs to Nearline after 30 days, delete after 365 |
createdBefore | Object was created before a date | One-time cleanup of legacy data |
isLive | Object is (or is not) the current version | Target only noncurrent versions in versioned buckets |
numNewerVersions | At least N newer versions exist | Keep only the last 3 versions of each object |
daysSinceNoncurrentTime | Version became noncurrent N days ago | Delete noncurrent versions 30 days after replacement |
matchesStorageClass | Object is in a listed storage class | Only transition Standard objects, skip already-cold ones |
Policies are written as JSON and applied to the bucket: gcloud storage buckets update gs://BUCKET_NAME --lifecycle-file=lifecycle.json. A canonical policy for versioned log data: transition to Nearline at 30 days, Coldline at 90, Archive at 365, and delete noncurrent versions once numNewerVersions exceeds 2. Transitions only move toward colder classes, and rules act on objects — they never re-warm data for you.
Two gotchas pair with the storage classes themselves. Nearline, Coldline, and Archive carry minimum storage durations (30, 90, and 365 days respectively) — deleting or transitioning earlier still bills the minimum — and they charge retrieval fees per GiB read. So a lifecycle rule that pushes frequently read data into Archive raises cost. If access patterns are unknown or shifting, Autoclass manages transitions automatically per object and removes the guesswork.
Executing queries against your data services
Each data service has a native query path, and the exam expects you to match tool to service. For Cloud SQL, connect with gcloud sql connect INSTANCE_NAME --user=root — it temporarily allowlists your IP and opens the familiar database shell — or run the Cloud SQL Auth Proxy for IAM-authenticated connections from applications without managing authorized networks or SSL certificates. From there it is ordinary SQL against your engine of choice. AlloyDB, the PostgreSQL-compatible service, works the same way conceptually: connect with standard PostgreSQL clients such as psql, typically through the AlloyDB Auth Proxy, or use AlloyDB Studio in the console.
For BigQuery, run SQL in the console's BigQuery Studio or from the bq CLI: bq query --use_legacy_sql=false 'SELECT name, COUNT(*) FROM dataset.table GROUP BY name'. Always use standard SQL. Before running an expensive query, a dry run (bq query --dry_run) reports how many bytes it would scan without billing you — remember this for cost questions. For Spanner, execute SQL with gcloud spanner databases execute-sql DATABASE_NAME --instance=INSTANCE_NAME --sql='SELECT ...' or use Spanner Studio in the console.
Bigtable is a NoSQL wide-column store — no SQL engine of its own. You read rows with the cbt CLI (cbt -instance=INSTANCE_ID read TABLE_NAME) or client libraries, and query it with SQL only indirectly, for example through a BigQuery external table. Firestore is a document database queried through client libraries and the console's query builder against collections and documents rather than tables. When a question hands you a service and asks how to run a query, eliminate by data model first: SQL for Cloud SQL, AlloyDB, Spanner, and BigQuery; cbt or client libraries for Bigtable; document queries for Firestore.
Estimating the cost of data storage
You estimate storage costs by combining three factors — volume stored, storage class or tier, and access pattern — and the Google Cloud pricing calculator is the tool for turning those into a number before you build. For Cloud Storage the estimate is monthly GiB stored per class, plus operation charges, plus retrieval fees for cold classes, plus any early-delete charges from minimum storage durations. The recurring exam trap: Archive storage is by far the cheapest at rest but expensive to touch, so the right class depends on how often data is read, not just how big it is.
BigQuery costs split into storage and compute. Storage is billed for data at rest (with a lower rate for long-term storage — tables or partitions unmodified for 90 days). Compute is either on-demand — billed per TiB of data scanned by each query — or capacity-based reservations billed for slots. On-demand is why partitioning and clustering matter operationally: a query that prunes to one day's partition scans and bills a fraction of the table, and a dry run tells you the scanned bytes in advance. Cloud SQL and AlloyDB bill for provisioned vCPUs, memory, and storage over time (plus backup storage), so their estimates look like VM sizing; Spanner bills for compute capacity plus storage; Bigtable bills for nodes plus storage.
After launch, cost observability replaces estimation: billing reports break down spend by service and SKU, and exporting billing data to BigQuery lets you query spend directly. If a scenario asks how to forecast the cost of a proposed storage design, answer the pricing calculator; if it asks how to analyze existing spend in detail, answer billing export to BigQuery.
Backing up and restoring database instances
For Cloud SQL, enable automated backups — daily backups taken in a configurable window — with gcloud sql instances patch INSTANCE_NAME --backup-start-time=03:00, and take on-demand backups any time with gcloud sql backups create --instance=INSTANCE_NAME. Restoring a backup overwrites or recreates the instance at that backup's moment. To recover to an arbitrary point between backups, enable point-in-time recovery (PITR), which requires automated backups plus transaction logging (binary logging on MySQL, write-ahead logging on PostgreSQL). PITR restores to a new instance at a chosen timestamp — the pattern for undoing an accidental DELETE without losing the rest of the day's writes.
| Service | Backup mechanism | Point-in-time recovery | Restore target |
|---|---|---|---|
| Cloud SQL | Automated daily + on-demand backups | Yes, with automated backups + transaction logs | Backup: same or new instance; PITR: new instance |
| AlloyDB | Automated + on-demand backups | Yes, via continuous backup and recovery | New cluster at chosen timestamp |
| Spanner | Backups (retained per your schedule) + import/export | Restore backups; stale reads via version retention for recent history | New database |
| Firestore | Scheduled backups + managed export to Cloud Storage | Yes, PITR retains recent versions for recovery reads and restores | New or existing database (import), backup restore to new database |
| Bigtable | Table-level backups stored in the instance | No general PITR; restore a backup | New table, same or another instance |
The pattern to internalize: backups restore to a state; PITR restores to a moment. Managed backups also differ from exports — a Firestore export to Cloud Storage or a Spanner export via Dataflow gives you portable data for migration or long-term archive, while native backups are faster to restore but live inside the service. When a question involves accidental data deletion minutes ago, look for the PITR-shaped answer; when it involves keeping a copy for years or moving data between projects, look for export.
Reviewing job status: Dataflow and BigQuery
You check Dataflow job status in the console's Dataflow Jobs page, where each job shows its state — Running, Succeeded, Failed, Cancelled — alongside the pipeline graph, per-step metrics, autoscaling history, and worker logs. From the CLI, gcloud dataflow jobs list --region=REGION enumerates jobs and gcloud dataflow jobs describe JOB_ID --region=REGION shows one job's detail. A streaming job that must stop has two options with an exam-relevant difference: drain finishes processing in-flight data then stops, while cancel stops immediately and may drop buffered records. Failed jobs are diagnosed from the step-level logs and error counters in the job page.
For BigQuery, every query, load, export, and copy runs as a job. In the console, Job history (personal and project-level) shows each job's status, duration, and bytes processed. From the CLI, bq ls -j --max_results=20 lists recent jobs and bq show -j JOB_ID prints one job's full status, including error details for failures. For fleet-wide analysis — slowest queries, biggest scanners, failure rates — query the INFORMATION_SCHEMA.JOBS views with SQL, which is also the standard answer for auditing who ran what.
Operationally, connect job monitoring to alerting rather than watching dashboards: Dataflow job metrics flow into Cloud Monitoring, where an alerting policy on failed jobs or rising system lag notifies you, and BigQuery job errors surface in Cloud Logging where log-based alerts apply. If a scenario asks how to find out why last night's scheduled load failed, the answer is the job's status detail (bq show -j or the console job history), not re-running the pipeline blind.
Managing the database fleet with Database Center
Database Center is the single console view of your entire database fleet — Cloud SQL, AlloyDB, Spanner, Bigtable, Firestore, and more — across projects, so you stop checking each instance page one by one. It inventories every database resource, then layers on health signals: availability risks such as instances without high availability or automated backups, security findings such as broad network exposure or missing encryption controls, performance issues, and cost optimization opportunities, largely powered by Active Assist recommenders.
The workflow is triage: open Database Center, review the fleet summary of issues grouped by category and severity, drill into an affected instance, and follow the recommendation — enable automated backups here, add high availability there, tighten a network setting elsewhere. It also carries a Gemini-powered chat interface, so you can ask natural-language questions about the fleet's health and get summarized answers instead of assembling them from per-instance pages.
For the exam, position it correctly against its neighbors: Database Center is fleet-wide inventory, health, and recommendations across database services; Cloud Monitoring is metrics and alerting for anything; Query Insights (in Cloud SQL and AlloyDB) diagnoses slow queries inside a single instance. A question about spotting every database in the organization missing backups is Database Center; a question about one instance's slow query is Query Insights.
Configuring customer-managed encryption keys (CMEK)
Everything in Google Cloud is encrypted at rest by default with Google-managed keys; CMEK changes who controls the key, not whether encryption happens. With CMEK, data is protected by a key you create and manage in Cloud KMS — you control its rotation schedule, you can disable or destroy it, and access to it is IAM-audited. Choose CMEK when compliance requires customer control of key lifecycle; the fully customer-supplied alternative (providing raw key material yourself) is rare and operationally heavy, so CMEK is the standard answer for key control requirements.
The setup has three steps and one critical grant. First, create a key ring and key: gcloud kms keyrings create my-ring --location=us-central1 then gcloud kms keys create my-key --keyring=my-ring --location=us-central1 --purpose=encryption. Second — the step exams test — grant the service agent of the data service permission to use the key: each service (Cloud Storage, Cloud SQL, BigQuery, Spanner) has a per-project service agent account that must hold roles/cloudkms.cryptoKeyEncrypterDecrypter on the key. Third, attach the key to the resource: set a bucket's default key with gcloud storage buckets update gs://BUCKET_NAME --default-encryption-key=KEY_RESOURCE_NAME, or pass the key at creation for a Cloud SQL instance, BigQuery dataset, or Spanner database — for many services CMEK can only be chosen at resource creation, not retrofitted.
The operational consequences are the point. The key must live in a location compatible with the resource it protects. If you disable or destroy the key — or revoke the service agent's role — the service can no longer decrypt: data becomes inaccessible, instances can fail to start, and destroyed key versions make data permanently unrecoverable. Key rotation is safe and non-disruptive: new key versions encrypt new data while old versions still decrypt existing data. A scenario where storage "suddenly became inaccessible" after a security cleanup is almost always a disabled CMEK key or a removed service agent grant.
Tip. Expect questions that pick the right sharing mechanism for Cloud Storage — signed URLs for temporary external access, uniform bucket-level access plus IAM for everything else — and lifecycle-rule design questions involving noncurrent versions, storage-class transitions, minimum storage durations, and retrieval fees. Database questions test Cloud SQL automated backups versus point-in-time recovery (PITR needs transaction logging and restores to a new instance) and which backup mechanism each service offers. CMEK questions hinge on the service agent's cryptoKeyEncrypterDecrypter grant and on what happens when a key is disabled or destroyed, and job-status questions expect bq show -j, gcloud dataflow jobs, and the drain-versus-cancel distinction.
- Prefer uniform bucket-level access so IAM alone governs Cloud Storage; fine-grained ACLs are legacy and only for per-object permission schemes.
- Signed URLs grant time-limited access to a single object without Google accounts or IAM changes — the answer for external, temporary sharing.
- Lifecycle rules pair actions (SetStorageClass, Delete) with conditions (age, isLive, numNewerVersions, daysSinceNoncurrentTime); cold classes carry minimum storage durations and retrieval fees.
- Match query tool to service: gcloud sql connect or the Auth Proxy for Cloud SQL, bq for BigQuery, gcloud spanner databases execute-sql for Spanner, cbt for Bigtable, client libraries for Firestore.
- Cloud SQL PITR needs automated backups plus transaction logging and restores to a new instance at an exact timestamp — backups restore to a state, PITR to a moment.
- Check jobs where they run: Dataflow Jobs page or gcloud dataflow jobs, and bq ls -j / bq show -j or INFORMATION_SCHEMA.JOBS for BigQuery; drain finishes in-flight streaming data, cancel drops it.
- Database Center gives fleet-wide inventory, health issues, and recommendations across all database services in one console view.
- CMEK requires granting the service agent roles/cloudkms.cryptoKeyEncrypterDecrypter on the Cloud KMS key; disabling or destroying the key makes the data inaccessible.
Frequently asked questions
When should I use a signed URL instead of an IAM binding in Cloud Storage?
Use a signed URL when someone outside your IAM world — an external partner, a customer's browser, a mobile app — needs temporary access to a specific object. The URL is signed with service account credentials, works without a Google account, and expires after the duration you set. Use IAM bindings for ongoing access by identities you manage, and never make a bucket public just to share one file.
What is the difference between object versioning and a lifecycle policy?
Versioning is a protection feature: it keeps noncurrent versions when objects are overwritten or deleted, so you can recover them. A lifecycle policy is an automation feature: rules that transition objects to colder storage classes or delete them based on conditions like age or number of newer versions. They work together — versioning creates noncurrent versions, and lifecycle rules with conditions like daysSinceNoncurrentTime clean them up so costs stay controlled.
How does point-in-time recovery work in Cloud SQL?
PITR combines automated backups with continuously retained transaction logs (binary logs on MySQL, write-ahead logs on PostgreSQL). To recover, Cloud SQL restores the closest backup and replays logs up to the timestamp you choose, creating a new instance at that exact moment. It must be enabled before the incident, and it restores to a new instance rather than overwriting the original — ideal for recovering from an accidental table deletion.
How do I check why a BigQuery scheduled load job failed overnight?
Look at the job's status detail: open Job history in the BigQuery console, or run bq ls -j to find the job and bq show -j JOB_ID to see its state and error message. For patterns across many jobs — repeated failures, slow queries, heavy scanners — query the INFORMATION_SCHEMA.JOBS views with SQL. The error detail on the failed job tells you the cause; re-running blind does not.
What breaks if I disable a CMEK key that protects a Cloud Storage bucket or database?
The service loses the ability to decrypt: objects become unreadable, and CMEK-protected database instances can fail or refuse to start. The same happens if you revoke the service agent's cryptoKeyEncrypterDecrypter role on the key. Disabling is reversible — re-enable the key version and access returns — but destroying a key version after its scheduled destruction completes makes the data permanently unrecoverable.
What does Database Center do that Cloud Monitoring does not?
Database Center is database-fleet-specific: it inventories every Cloud SQL, AlloyDB, Spanner, Bigtable, and Firestore resource across projects and flags availability, security, performance, and cost issues — like instances missing automated backups or high availability — with recommendations, plus a Gemini chat interface for fleet questions. Cloud Monitoring is general-purpose metrics, dashboards, and alerting for any resource; it will chart a database's CPU but will not tell you which databases across the fleet lack backups.
Sign up free to mark lessons complete, bookmark topics and track your exam readiness.