SYSTEM Cited by 1 source
PlanetScale Portals¶
What it is¶
PlanetScale Portals is PlanetScale's managed read-only region feature for its MySQL / Vitess product: a single writing region can be paired with N fully-replicated read-only regions, each sitting close to an application tier, each exposed as a distinct MySQL endpoint. Launched 2022-05-24 (Taylor Barnett, source post).
From the launch post: "Portals allow you to read data from regions closest to where you globally deploy your applications. Whether your application is deployed near Northern Virginia, Frankfurt, São Paulo, or any of our other PlanetScale regions, Portals can now provide lower read latency for your applications!" (Source: sources/2026-04-21-planetscale-introducing-planetscale-portals-read-only-regions.)
The shape¶
┌────────────────────┐
│ writing region │
writes ──────────► │ (e.g. us-east) │ ◄──── all writes go here
│ primary cluster │
└─────────┬──────────┘
│ async replication (Vitess)
┌───────────────────┼───────────────────┐
▼ ▼ ▼
┌────────────┐ ┌──────────────┐ ┌─────────────┐
│ Frankfurt │ │ São Paulo │ │ Singapore │
│ read-only │ │ read-only │ │ read-only │
│ region │ │ region │ │ region │
└─────▲──────┘ └──────▲───────┘ └──────▲──────┘
│ │ │
Frankfurt app SP app SG app
(reads local) (reads local) (reads local)
Each read-only region gets:
- A full dataset copy, kept up to date via replication from the writing region.
- A region-specific MySQL endpoint (its own hostname + credential in the 2022 model, or a single global credential that resolves to the nearest region in the 2024+ Global Network model).
- A separate billing line for row-reads served from that region, and a full storage charge (the dataset is genuinely copied — see Pricing below).
What it does (and doesn't)¶
Does:
- Moves read latency from "cross-ocean RTT per query" to "in-region RTT per query" — canonical measured delta in the launch post: ~90 ms → ~3 ms for a Frankfurt app previously dialing a Northern-Virginia primary. See concepts/edge-to-origin-database-latency.
- Scales aggregate read throughput: each region has its own connection capacity + its own replica servers.
- Integrates with standard ORM read-write-splitting machinery — the launch post walks through Rails' multiple-databases + automatic role switching as the canonical application-side integration.
Does not:
- Scale writes. "Today, each database in PlanetScale reads and writes from a single region." Writes still go to the one writing region; Portals is not multi-primary, not Spanner-style, not a geo-partitioned write substrate. Write-scaling is the Vitess / sharding story, a different dimension.
- Provide strong cross-region consistency. Replicas are eventually consistent, lagging by whatever the cross-region replication pipeline's tail latency is. Read-your-writes preservation is the caller's responsibility — see patterns/session-cookie-for-read-your-writes.
- Behave like a CDN. Each region is a MySQL endpoint; the 2024 Global Network launch added the CDN-shaped edge-connection-termination layer on top.
2022 connection model: per-region credential¶
Per the launch post: "You connect to your new read-only regions with a connection string, just like connecting to any other PlanetScale database branch or other MySQL databases. This connection string is specific to both your read-only region and production branch." The routing decision lives in the application, keyed to whatever environment variable identifies the pod's deployment region:
region = ENV["APP_REGION"]
region_replica_mapping = {
"fra" => Rails.application.credentials.planetscale_fra,
"gra" => Rails.application.credentials.planetscale_gra,
}
db_replica_creds = region_replica_mapping[region] ||
Rails.application.credentials.planetscale
This is the per-region-credential model — N credentials for N regions, application picks which hostname to dial. See patterns/per-region-read-replica-routing.
Superseded by: global replica credentials (2024), which collapse N per-region credentials into a single credential; routing to the nearest replica becomes a Global-Network job. Portals itself — the "there is a read-only region here" resource — remains; only the connection model evolved.
Read-your-writes: the 2-second cookie¶
A naive replica-read architecture lets a user hit "Save", then
immediately reload, then not see what they just wrote — the read
request goes to a replica whose replication cursor is behind the
write. The post's recipe: use Rails' DatabaseSelector middleware
to pin that user's reads to the primary for 2 seconds after each
write:
config.active_record.database_selector = { delay: 2.seconds }
config.active_record.database_resolver = ActiveRecord::Middleware::DatabaseSelector::Resolver
config.active_record.database_resolver_context = ActiveRecord::Middleware::DatabaseSelector::Resolver::Session
The mechanism is a session cookie set on every write; for the next 2 s the cookie's presence routes that user's reads back to primary. Other users continue reading from the in-region replica. See concepts/session-cookie-read-your-writes-window and patterns/session-cookie-for-read-your-writes.
Correctness condition: the window must exceed p99 cross-region replication lag, or users can still hit ghost-writes. 2 s is a reasonable default for a healthy Vitess replication setup; the number is configurable.
Pricing shape¶
From the post: storage charge scales linearly with region count — "if your production branch is 10GB, each read-only region added will increase your total storage cost by 10GB" — which is honest about the architecture: each region is a full dataset copy, not a logical slice. Row-reads are billed per-region on the invoice, so operators can see which regions are pulling load. Available on Base or Enterprise plans; beta at launch.
Relationship to the rest of PlanetScale¶
- systems/planetscale — PlanetScale's database product; Portals is one of its regional-scaling primitives.
- systems/vitess — the underlying substrate; Portals is essentially managed VReplication / MySQL async replication + Vitess-aware routing, packaged as a first-class product feature.
- systems/planetscale-global-network (2024+) — the CDN-shaped edge layer that later subsumes the 2022 per-region-credential connection model.
- companies/flyio / systems/fly-machines — the launch post explicitly pairs with Fly.io's global compute platform; the canonical 2022-era app-near-user + DB-near-app architecture.
Extended by later posts¶
- sources/2026-04-21-planetscale-introducing-global-replica-credentials — 2024 follow-up that swaps the per-region-credential model for a single global credential resolved via the Global Network.
Seen in¶
Related¶
- systems/planetscale, systems/planetscale-global-network, systems/vitess, systems/vitess-vreplication, systems/mysql, systems/ruby-on-rails
- concepts/regional-read-replica, concepts/read-your-writes-consistency, concepts/replication-lag, concepts/edge-to-origin-database-latency, concepts/session-cookie-read-your-writes-window, concepts/read-write-splitting
- patterns/per-region-read-replica-routing, patterns/session-cookie-for-read-your-writes, patterns/read-replicas-for-read-scaling
- companies/planetscale, companies/flyio