If your exec asks "when us-east-1 goes dark, how fast can Finance be back online, and who can still read PII?" the right answer to a multi-region, multi-account Snowflake footprint is designed, not guessed. This guide lays out the real options - data sharing vs. replication vs. failover - and how they map to RPO/RTO and access-control requirements without lighting your spend on fire.
Why it matters
- Multi-region gives regulatory coverage, latency control, and disaster recovery.
- Multi-account gives strong blast-radius boundaries, autonomy for BU/geo teams, and least-privilege governance.
- The hard part is choosing between live sharing, periodic replication, and promotable failover (per database or as grouped objects) while keeping RPO/RTO and RBAC honest.
The building blocks
1) Cross-account data sharing (direct share / listings)
- What it is: a provider grants read-only access to specific objects to a consumer account (same or different region/cloud).
- Why: zero-ETL distribution to many consumers; no copy jobs; consumers query live provider data.
- RPO/RTO: effectively RPO ≈ 0 for published objects; RTO ≈ 0 for read queries (no promotion step).
- Caveat: no write access on the consumer; not a DR solution for writes.
Governance fit: tight, object-level grants; overlay row access / masking for PII; create separate shares per audience.
2) Database replication (primary → secondary)
- What it is: Snowflake replicates a read-only secondary database in a target account/region.
- Why: off-region analytics copies; warm standby for DR; minimize egress and operational glue.
- RPO/RTO: RPO = replication interval (minutes to hours); RTO = promotion time (seconds to minutes).
- Caveat: the secondary is read-only until you promote it. Writes resume after switchover/failover.
3) Failover (promote secondary → primary)
- What it is: turn a replicated secondary into the new primary (planned switchover or unplanned failover).
- Why: true continuity for write workloads when a region/account is impaired.
- RPO/RTO: driven by your replication schedule (RPO) and the promotion + connection cutover time (RTO).
4) Grouping objects for org-wide DR
- What it is: treat multiple databases + grants + other selected objects as a unit so they replicate and fail over together, avoiding "oops, forgot that database" incidents.
- Why: consistency across apps that span several databases and shared objects.
If your DR plan requires engineers to remember five manual steps under stress, you don't have a DR plan - you have a fantasy. Group things.
Choosing the right pattern
| Use case | Pattern | RPO | RTO | Notes |
|---|---|---|---|---|
| Share curated facts to 10+ consumer accounts | Data Sharing | ~0 | ~0 | Perfect for distribution; not for write continuity |
| Analytics read copies closer to users/BI | Database Replication | Minutes - Hours | Minutes | Consumers read from secondary; primary continues writes |
| Full DR for write workloads | Replication + Failover | Minutes | Minutes | Test switchover quarterly; automate connection flips |
| Multi-tenant BUs with strict isolation | Multi-Account + Sharing | ~0 | ~0 | Each BU owns compute; central team curates datasets |
| Regulated PII with geo boundaries | Per-region primaries + sharing by region | ~0 | ~0 | Overlay row/mask policies per jurisdiction |
Reference architectures
- Hub-and-spoke (most common): a central hub account in Region A publishes shares to regional spokes for read workloads. Critical write databases replicate to a paired DR account in Region B with a defined failover runbook.
- Active/active read, active/passive write: reads served locally via replicated secondaries in each region; a single write primary with failover rights to the secondary region.
- Producer → exchange → consumers: producers publish via listings/shares to many consumers (partners, BUs). DR for the producer is handled by replication/failover; consumers are unaffected.
Practical SQL snippets
You need appropriate org-level/admin privileges. Exact options vary by account/edition - treat these as patterns.
A) Share data cross-account (read-only)
-- Provider account
CREATE SHARE sales_share;
GRANT USAGE ON DATABASE SALES TO SHARE sales_share;
GRANT USAGE ON SCHEMA SALES.MART TO SHARE sales_share;
GRANT SELECT ON ALL TABLES IN SCHEMA SALES.MART TO SHARE sales_share;
-- Include future tables to avoid drift
GRANT SELECT ON FUTURE TABLES IN SCHEMA SALES.MART TO SHARE sales_share;
-- Allow a target consumer (by account locator or org name + account)
ALTER SHARE sales_share ADD ACCOUNTS = ('ORG1.ACCOUNT_B_ANALYTICS');
Consumer side:
-- In consumer account
CREATE DATABASE SALES_REMOTE FROM SHARE ORG1.PROVIDER_ACCOUNT.sales_share;
-- Now query like a normal DB (read-only)
SELECT * FROM SALES_REMOTE.MART.ORDERS_DAILY;
B) Replicate a database to another region/account
-- On the primary account
ALTER DATABASE SALES ENABLE REPLICATION TO ACCOUNTS = ('ORG1.DR_ACCOUNT');
-- On the DR account: create secondary and refresh on schedule
CREATE DATABASE SALES_DR AS REPLICA OF ORG1.PRIMARY_ACCOUNT.SALES;
-- Later, pull changes (you'll automate this)
ALTER DATABASE SALES_DR REFRESH;
Planned switchover / unplanned failover:
-- In DR account, promote the secondary to primary when needed
ALTER DATABASE SALES_DR PRIMARY; -- promotion step
-- (Re-point roles/warehouses/connections to the new database name/endpoint)
C) Access control overlays (masking & row access)
-- Example: role-based dynamic masking policy for PII
CREATE MASKING POLICY mask_email AS (val STRING) RETURNS STRING ->
CASE WHEN current_role() IN ('PII_READ') THEN val
ELSE REGEXP_REPLACE(val, '(^.).+(@.*$)', '\\1***\\2') END;
ALTER TABLE SALES.CUSTOMERS MODIFY COLUMN EMAIL SET MASKING POLICY mask_email;
-- Row-level filter for region-restricted data
CREATE ROW ACCESS POLICY eu_only AS (region STRING) RETURNS BOOLEAN ->
region = 'EU' OR current_role() IN ('GLOBAL_AUDIT');
ALTER TABLE SALES.CUSTOMERS ADD ROW ACCESS POLICY eu_only ON (REGION);
RPO/RTO by design
- Data sharing - RPO ~0 for published objects (consumers see current provider state); RTO ~0 for reads; no write continuity, by design.
- Replication (no promotion) - RPO is your refresh cadence (e.g., 5-15 minutes); RTO ~0 for read queries on the already-online secondary.
- Failover (promotion) - RPO is the last successful replication; RTO is minutes, dominated by promotion plus client routing (JDBC/ODBC URLs, secrets, BI connections, dbt profiles). If you haven't rehearsed connection flips and secrets rotation, add 15-60 minutes of chaos to your RTO.
Best practices
- Separate blast radii with multi-account. Central ORGADMIN/SECURITYADMIN only; each BU gets ACCOUNTADMIN in its own account without org-wide rights.
- Use shares for distribution, replication for resilience. Don't use replication to feed 20 consumers - share once, not copy 20×.
- Group what fails over together. Bundle all databases that form one app boundary, including required grants and reference data, and treat it as a unit.
- Automate the boring parts. Scheduled REFRESH, pre-created warehouses/roles in DR, and IaC (Terraform Snowflake Provider) for all grants.
- Make connection cutover trivial. Use DNS aliases or connection managers so BI/dbt/apps swap endpoints via one variable/secret.
- Tighten least privilege before you replicate. If prod roles are messy, DR copies the mess. Enforce RBAC, masking, row policies, network policies, and session parameters now.
- Test quarterly. Run a game day: stop replication, promote the secondary, re-run SLA queries, validate lineage, and fail back.
- Control cost. Replicate only hot marts; leave raw/bronze as shared or re-creatable. Keep DR warehouses small until an event.
Common pitfalls
- Relying on shares for DR. Shares are for read distribution, not write continuity.
- Forgetting future grants. New tables won't be visible if you omit GRANT ... ON FUTURE TABLES.
- Orphaned policies. Masking/row-access policies must exist in the target; replication handles database objects, but check dependencies.
- Manual runbooks. Clicking through the UI in an outage is how you miss steps. Script it.
- Ignoring metadata consumers. Lineage, quality dashboards, and audits need to follow the cutover too.
Worked example
Goal: US primary writes; EU read latency < 100ms; DR in EU with 15-minute RPO.
1. US primary account
SALESdatabase → ENABLE REPLICATION toEU_DR_ACCOUNT.- Publish
sales_share(curated marts) to the EU Analytics account.
2. EU Analytics account
CREATE DATABASE SALES_REMOTE FROM SHARE ….sales_sharefor read-only BI.- No local copies, so no ETL drift.
3. EU DR account
CREATE DATABASE SALES_DR AS REPLICA OF ….SALES.- CRON refresh every 15 minutes; keep small warehouses idled.
4. Runbook
- If the US region fails:
ALTER DATABASE SALES_DR PRIMARY; - Flip a single DNS alias / secret used by BI and apps → new Snowflake account URL.
- Post-incident: perform failback after the US recovers and replication is healthy.
Outcome: EU BI never stopped (reads via share), and write systems resumed in minutes in EU DR with RPO ≤ 15 min.
Access control at scale
- Org-level: centralize identity via SSO/SCIM; standardize role names across accounts (
APP_READ,APP_WRITE,PII_READ). - Per account: keep ACCOUNTADMIN for ops with no data access; app roles inherit from functional roles; grant to roles, never to users; apply masking/row policies in the data layers closest to consumers.
- Secrets & endpoints: store in a central secrets manager; reference by logical alias so failover is configuration, not code changes.
Takeaways
- Use data sharing for distribution, replication for warm copies, and failover for write continuity.
- Define RPO/RTO explicitly and back them with automation: refresh schedules, scripted promotion, endpoint flips.
- Bake in RBAC plus masking/row policies before copying data across regions/accounts.
- Test quarterly. If you haven't practiced, your RTO is fiction.



Leave a Comment