Every Cloud Storage bucket has a location, and it is fixed when you create the bucket unless you later pay for a relocation. The choice is between a single region, a dual-region (two specific regions) and a multi-region (a large area such as the US or the EU). It decides where your bytes live, how much an outage of one region hurts, how much data you can lose, what you pay per gigabyte stored and written, and how far your compute sits from your data.
The common mistake is to treat this as an availability checkbox and tick the biggest one. This article explains what actually happens on a write and a read in each location type, what the replication targets promise and what they do not, how to monitor and change the setting, and how to choose with a cost model rather than a hunch.
Three location types, from where the copies are
Start from where the copies are.
- Regional buckets keep data in one region, spread across zones. A zone failure is absorbed. A whole-region outage makes the bucket unavailable until the region returns.
- Dual-region buckets keep data in two named regions in the same area. You can use a predefined pair, such as
NAM4(Iowa and South Carolina), or pick a configurable pair yourself. You know exactly which two regions hold the bytes, which matters for both latency and data residency. - Multi-region buckets (
US,EUandASIA) keep data in at least two regions inside a large area, and Google chooses which. You get the same geo-redundancy with less control over placement.
Dual- and multi-region buckets are a single bucket with a single namespace and one set of object names. Clients do not pick a region, there is nothing to fail over in your code, and metadata is strongly consistent everywhere. That is the main thing they buy you over running two regional buckets with your own copy job. The price is that you cannot see or control the replication process directly, apart from choosing its speed.
What a write waits for
The documentation is precise about the acknowledgement, and it is worth reading slowly. A write to a dual- or multi-region bucket is confirmed as successful only after the data is stored redundantly in one initial region, across at least two availability zones. Copying to the second region happens afterwards, asynchronously.
So the latency of a write to a dual-region bucket is close to the latency of a regional write. You are not paying a cross-region round trip per upload. It also means there is a window in which a newly acknowledged object exists in only one region. How long that window lasts is set by the bucket's recovery point objective (RPO).
Replication targets: default and turbo
There are two replication settings, exposed as the bucket's rpo field.
| Setting | rpo value | Target | Available on |
|---|---|---|---|
| Default replication | DEFAULT | 99.9% of newly written objects within one hour; 100% within 12 hours | Dual-region and multi-region |
| Turbo replication | ASYNC_TURBO | 100% of newly written objects within 15 minutes | Dual-region only |
Read the default target carefully. "99.9% within an hour" means one object in a thousand may take longer, up to 12 hours. For a bucket receiving a million objects a day, that is about a thousand objects a day that might exist in only one region for more than an hour. For media archives that is usually fine. For a ledger of financial exports that downstream systems in another region must read soon after writing, it may not be.
Turbo replication tightens the target to 15 minutes for every object. It costs a premium on each gigabyte written, and it applies only to dual-regions. A multi-region bucket cannot use it. If you need a guaranteed 15-minute RPO, that requirement alone picks the location type.
Both are targets, not synchronous guarantees. The Cloud console reports two indicators for replication health: percent of minutes out of RPO and percent of objects out of target. Put both on the dashboard of any bucket whose RPO appears in a disaster recovery plan, and alert when they rise. A replication backlog you cannot see is an RPO you do not have.
Reads and outages under strong consistency
During a regional outage, a dual- or multi-region bucket keeps serving every object that had already been replicated to the surviving region, with no client change. Objects written within the RPO window that had not yet replicated are unavailable until the failed region recovers. They are not lost, provided the region comes back, but they cannot be read.
Strong consistency holds through this. The documentation states that stale versions are not served and that later overwrites are not reverted when the failed region returns. Concretely, suppose version 1 of report.csv has replicated, you write version 2, and the initial region fails before version 2 replicates. Readers get an error for that object rather than silently reading version 1. Writers who overwrite again during the outage do not see their write rolled back when the old region rejoins.
Design consequences follow directly:
- Readers must treat an error on a recently written object as retryable during an incident, not as "object missing, regenerate it". Regenerating can create conflicting versions.
- Pipelines that write a marker object after their data (a
_SUCCESSfile, a manifest) can see the marker replicated before some data files. Consumers in the other region should check that every listed file is readable before acting. - A regional bucket offers no read path at all during a regional outage. If the RTO in your plan is shorter than a plausible regional outage, a regional bucket cannot meet it on its own.
Predefined and configurable dual-regions
The predefined dual-regions are listed below. Each bills against its own location SKU.
| Code | Regions |
|---|---|
ASIA1 | asia-northeast1 (Tokyo) + asia-northeast2 (Osaka) |
EUR4 | europe-north1 (Finland) + europe-west4 (Netherlands) |
EUR5 | europe-west1 (Belgium) + europe-west2 (London) |
EUR7 | europe-west2 (London) + europe-west3 (Frankfurt) |
EUR8 | europe-west3 (Frankfurt) + europe-west6 (Zurich) |
NAM4 | us-central1 (Iowa) + us-east1 (South Carolina) |
Configurable dual-regions let you pick the pair, with one rule: both regions must share the same location code (both in US, both in EU, and so on). The useful pattern is to pick the two regions where your compute already runs, so that every job reads from a copy in its own region. Note that two regions in different countries can still share a code. If residency rules restrict you to one country, check the pair against them.
Creating, tuning and relocating buckets
Creation and the RPO switch are a few commands. For a configurable pair, --location is the shared location code and --placement names the two regions. Turbo replication is then set on the existing bucket.
# Regional bucket next to the training cluster
gcloud storage buckets create gs://acme-train-scratch \
--location=us-central1 --uniform-bucket-level-access
# Configurable dual-region pinned to the two regions that run compute
gcloud storage buckets create gs://acme-ledger-exports \
--location=US --placement=us-central1,us-east4 \
--default-storage-class=STANDARD --uniform-bucket-level-access
# Tighten replication to the 15-minute target, then confirm
gcloud storage buckets update gs://acme-ledger-exports --rpo=ASYNC_TURBO
gcloud storage buckets describe gs://acme-ledger-exports --format="default(rpo)"
# Back to default replication when the requirement goes away
gcloud storage buckets update gs://acme-ledger-exports --rpo=DEFAULTChanging location used to mean creating a new bucket, copying everything and updating every client. Bucket relocation now does this in place: gcloud storage buckets relocate gs://BUCKET --location=LOCATION, with --dry-run to check feasibility first. It copies incrementally while the bucket stays writable. Depending on source and destination, it may end with a final synchronization during which writes are blocked, and the tool tells you whether that applies. Relocations without write downtime take at least seven days regardless of size. Buckets using customer-managed or customer-supplied encryption keys, retention policies or holds cannot be relocated, so check those first.
The cost model
The bill has four parts that differ by location type. Storage per GB-month is lowest for regional buckets. Dual-regions are billed as storage in each of the two underlying regions. Writes to dual- and multi-region buckets carry an inter-region replication charge per GiB written, and turbo replication raises that per-GiB charge. Reads that cross region or continent boundaries carry network data-transfer charges, which depend on where the reader sits relative to the data. Operation charges and storage class rules (see the storage classes article linked below) apply on top.
Because prices change and vary by region, the script below takes them as inputs. Fill it from the current pricing page for your regions and it gives a monthly comparison.
import json
def monthly_cost(stored_gb, written_gib, cross_region_read_gb, price):
"""price: dict of per-unit prices for ONE location option, taken from the pricing page."""
return (stored_gb * price["storage_gb_month"]
+ written_gib * price.get("replication_gib", 0.0) # 0 for regional
+ cross_region_read_gb * price.get("transfer_gb", 0.0))
PRICES = json.load(open("gcs_prices.json")) # your per-option prices, copied from the pricing page
workload = dict(stored_gb=200_000, written_gib=30_000)
options = {
# cross_region_read_gb: data that must leave its region to reach the readers
"regional": (60_000, PRICES["regional"]), # half the readers sit elsewhere
"dual-region": (0, PRICES["dual"]), # readers sit in the two regions
"dual + turbo": (0, PRICES["dual_turbo"]),
"multi-region": (0, PRICES["multi"]),
}
for name, (xread, price) in options.items():
print(f"{name:13s} {monthly_cost(cross_region_read_gb=xread, price=price, **workload):>10,.0f}")The shape of the answer is predictable even before you fill in prices. For write-heavy, rarely read data, the replication charge dominates and regional wins unless an RPO requirement says otherwise. For read-heavy data consumed from two regions, a dual-region can be cheaper than a regional bucket because it removes cross-region reads. That is the case people miss when they assume geo-redundancy is always the expensive option.
Worked example: three datasets, three answers
Consider one company with three datasets.
- Training data and checkpoints for a GPU cluster in us-central1: about 200 TB, rewritten often, read at very high throughput from that one region. Choose a regional bucket in us-central1. Cross-region copies would cost replication on every checkpoint, and a regional outage stops the cluster anyway, so a second copy buys little. Protect the few irreplaceable artifacts, such as final model weights, by copying them to a second bucket.
- Daily ledger exports consumed by services in us-central1 and us-east4, with a written requirement of no more than 15 minutes of data loss: choose a configurable dual-region on exactly those regions with turbo replication. It is the only option with a 15-minute RPO target, and both consumers read locally.
- Public product images served through a CDN to users across the US: choose the
USmulti-region. The CDN hides origin latency, the default RPO is fine for images that can be re-rendered, and you do not need to control which regions hold them.
The rule that generalizes is: put the bytes where the compute that reads them runs, buy geo-redundancy only for data whose loss or unavailability has a stated cost, and buy turbo only for data with a written RPO below what default replication offers.
Failure modes
| Failure mode | How it shows up | Prevention |
|---|---|---|
| Multi-region bucket, compute in one region | Unexpected network charges and higher read latency for heavy jobs | Co-locate: regional or a dual-region that includes the compute region |
| Assuming the ack means two regions | Data written minutes before an outage is unreadable during it | Treat the RPO window as real; use turbo where it matters; retry rather than regenerate |
| DR plan cites an RPO nobody measures | Replication backlog discovered during an incident | Dashboard and alert on minutes out of RPO and objects out of target |
| Marker file read before data | Consumer in the second region processes a partial batch | Verify every manifest entry is readable before processing |
| Relocation blocked late | Planned move fails on CMEK or retention settings | Run the dry run first; plan key and retention changes |
| Residency violated by a valid pair | Data stored in two countries under one location code | Check both regions of the pair against residency rules |
Operating the decision
Record the location decision with its reason, because nobody remembers in two years why a bucket is a dual-region. Keep a short table per bucket: location, RPO setting, the requirement it serves and who owns it. Review it when compute moves region. Location is the one bucket property that a refactor of your compute quietly invalidates.
Geo-redundancy is not backup. Replication faithfully copies deletions and overwrites to the second region. Protection against bad writes comes from object versioning, soft delete and retention settings, not from location.
For more depth, read how Cloud Storage works inside for the metadata layer behind its strong consistency, multi-region architecture on GCP for the compute side of a two-region design, storage classes for the cost dimension that sits on top of location, and lifecycle management for expiring the data you replicate.
What to do next
- List every bucket with its location, RPO setting and the regions where its readers and writers run.
- Flag buckets whose readers are in a different region from the data; price a dual-region that covers both.
- Flag multi-region buckets read mainly from one region; price the regional alternative.
- For each bucket named in a DR plan, write down the required RPO and check that the bucket type can meet it; enable turbo only where the requirement is below default replication.
- Add the two replication indicators to dashboards with alerts for those buckets.
- Make consumers retry unreadable recent objects during incidents instead of regenerating them.
- Before any location change, run
gcloud storage buckets relocate --dry-runand resolve encryption and retention blockers.