Connection & Credential Naming Standard
A Hyperdrive config bakes in exactly one MySQL user and one password. So the moment a database needs both a read-only and a read-write role, the split propagates through the entire access chain: two MySQL users, two secrets, sometimes two origin hostnames, two Hyperdrive configs, and two Worker bindings. This standard fixes one name at every link so that, given a database, an environment, and an access mode, every name in the path is derivable without lookup.
This standard governs the console, aggregate, and billing databases and applies identically to any future database reached through Hyperdrive.
The access chain
Section titled “The access chain”Every Worker-to-database connection runs the same path: a binding resolves to a Hyperdrive config, which connects to a public hostname that Cloudflare Access protects and cloudflared proxies to the private RDS or Aurora endpoint. The read-write binding carries the write grant and reaches the writer endpoint; the read-only binding carries only SELECT and, in production, reaches the Aurora reader endpoint.
The two axes
Section titled “The two axes”Two independent distinctions run through the whole chain, and keeping them separate is what makes the naming predictable.
The access mode, read-only (ro) or read-write (rw), is enforced by MySQL grants and therefore lives on the MySQL user. It is the same concept in every environment, so its name does not carry the environment.
The endpoint, writer or reader, is a property of the physical database and therefore lives on the origin hostname. Only Aurora clusters expose a separate reader endpoint, so only production has two hostnames per database; the single-instance environments have one.
Everything else in the chain (secret, Hyperdrive config, binding) carries whichever segments it needs to stay unique.
Logical databases
Section titled “Logical databases”| Logical DB | Contents |
|---|---|
console | User and Adventive Console system tables |
aggregate | Aggregate analytics rollups |
billing | Residual Adventive-side billing data (Stripe billing transition); shares the production Aurora cluster with console |
Environments and physical endpoints
Section titled “Environments and physical endpoints”Development and staging are each a single Standard MySQL instance that hosts all three databases (console, aggregate, billing). Production is two Aurora MySQL clusters: the production cluster hosts both console and billing, and the aggregate cluster hosts aggregate. Each Aurora cluster exposes a writer (cluster) endpoint and a reader (cluster-ro) endpoint.
| Env | Zone | Engine | Databases and endpoints |
|---|---|---|---|
dev | adventive.dev | Standard MySQL instance | console, aggregate, billing on development.coi6rcntfbgg.us-east-1.rds.amazonaws.com |
stg | adventivestg.com | Standard MySQL instance | console, aggregate, billing on staging.coi6rcntfbgg.us-east-1.rds.amazonaws.com |
prd | adventive.com | Aurora MySQL clusters | production cluster (console + billing), writer production.cluster-coi6rcntfbgg.us-east-1.rds.amazonaws.com · reader production.cluster-ro-coi6rcntfbgg.us-east-1.rds.amazonaws.com; aggregate cluster (aggregate), writer aggregate.cluster-coi6rcntfbgg.us-east-1.rds.amazonaws.com · reader aggregate.cluster-ro-coi6rcntfbgg.us-east-1.rds.amazonaws.com |
Because console and billing share the production cluster, their production credentials connect to the same writer and reader endpoints, they are distinguished by the Hyperdrive config’s database field and the MySQL user, not by a different host.
console and billing sharing the production cluster.The Aurora reader endpoint is the writer endpoint with cluster- replaced by cluster-ro-; it load-balances across the cluster’s replicas. Read-only traffic in production targets the reader endpoint so that read load stays off the writer.
Aurora endpoint types
Section titled “Aurora endpoint types”An Aurora cluster publishes more than one hostname, and the difference is a failover-correctness issue, not a preference:
- Cluster (writer) endpoint:
<cluster>.cluster-<hash>.<region>.rds.amazonaws.com. Always resolves to the current writer and follows failover automatically. The read-write target. - Reader endpoint:
<cluster>.cluster-ro-<hash>.<region>.rds.amazonaws.com. Load-balances across the cluster’s replicas and follows failover. The read-only target. In a single-instance cluster it resolves to the writer until a replica is added. - Instance endpoints:
<instance-id>.<hash>.<region>.rds.amazonaws.com(noclusterin the name). Each points to one specific instance regardless of that instance’s current role, and does not move on failover. AWS documents these for diagnosis and tuning only.
The aggregate cluster, for example, publishes all of these; only the first two are valid Hyperdrive origins:
| Hostname | Type | Hyperdrive origin? |
|---|---|---|
aggregate.cluster-coi6rcntfbgg.us-east-1.rds.amazonaws.com | cluster / writer endpoint | Yes, rw |
aggregate.cluster-ro-coi6rcntfbgg.us-east-1.rds.amazonaws.com | reader endpoint | Yes, ro |
aggregate.coi6rcntfbgg.us-east-1.rds.amazonaws.com | instance endpoint | No |
aggregate-us-east-1a.coi6rcntfbgg.us-east-1.rds.amazonaws.com | instance endpoint | No |
The production cluster (hosting console and billing) publishes the same four shapes. Never point a Hyperdrive origin at an instance endpoint. An instance’s writer/reader role is current-state only: after a failover the instance behind …-us-east-1a… can become a replica and the instance behind the bare aggregate… name can become the writer. A config bound to an instance endpoint would then be writing to a read-only replica (errors) or sending reads to the writer (no offload), and would not recover when the roles move. The cluster and reader endpoints exist precisely to abstract this away, they always track the writer and the replica pool. In this standard the rw hostname maps to the cluster endpoint and the ro hostname to the reader endpoint, so the cloudflared ingress rule is the only place an Aurora endpoint is named, and it names the two failover-aware ones.
MySQL users
Section titled “MySQL users”Four users per logical database, a read-only and a read-write user, env-agnostic. The same names exist on every host that carries that database, so one idempotent GRANT script runs identically on the dev instance, the staging instance, and the production Aurora clusters.
| User | Mode | Grants (scoped to its own schema only) |
|---|---|---|
hd_console_ro | read-only | SELECT on console.* |
hd_console_rw | read-write | SELECT, INSERT, UPDATE, DELETE, EXECUTE on console.* |
hd_aggregate_ro | read-only | SELECT on aggregate.* |
hd_aggregate_rw | read-write | SELECT, INSERT, UPDATE, DELETE, EXECUTE on aggregate.* |
hd_billing_ro | read-only | SELECT on billing.* |
hd_billing_rw | read-write | SELECT, INSERT, UPDATE, DELETE, EXECUTE on billing.* |
Rules that make the users safe and portable:
- Schema-scoped grants only. Each user is granted on its own database (
console.*,aggregate.*, orbilling.*), never*.*. This matters wherever one host carries multiple databases: the dev and staging instances hold all three, and the production cluster holds bothconsoleandbilling, sohd_console_romust not be able to readbilling. - No DDL. Neither role may
CREATE,ALTER, orDROP. Schema migrations run under a separate, deliberately elevated migration credential that is out of scope for this standard. The read-write role is for application DML, not schema change. - Host-scope to the tunnel. All connections arrive from
cloudflaredinside the VPC, so scope the user host to the tunnel’s private-subnet CIDR (for example'hd_console_ro'@'10.0.%') rather than'...'@'%'. Use@'%'only where the source range cannot be pinned, and record that as a known gap. - Env-agnostic. The username never carries the environment. The environment is unambiguous from the hostname, the Hyperdrive config name, and the secret name; encoding it a fourth time on the user only multiplies names and breaks the single-GRANT-script property.
Passwords
Section titled “Passwords”A password value is never standardized, only how it is generated, stored, and rotated.
- One distinct password per (database, mode, environment). No password is reused across environments or across the read-only and read-write roles. For
console,aggregate, andbillingthat is eighteen secrets in total. - Generated, never chosen. Generate with
aws secretsmanager get-random-password --exclude-punctuation --require-each-included-type --password-length 32. Punctuation is excluded so the value survives every connection-string and URL-encoding path Hyperdrive and tooling put it through, with no escaping edge cases. - Never committed, never pasted. Password values do not appear in Git, in Terraform state as plaintext, in CI logs, in runbooks, or in this repository. They live only in AWS Secrets Manager and, encrypted, inside the Hyperdrive config.
- Rotate at least every 90 days and on any personnel change. Rotation updates the value in two places: the Secrets Manager secret and the Hyperdrive config’s baked-in copy, plus
ALTER USERon the database. The procedure is in Credential provisioning.
AWS Secrets Manager
Section titled “AWS Secrets Manager”Every database credential’s system of record is AWS Secrets Manager, out-of-band from Cloudflare, consistent with the existing Adventive AWS keystore. Hyperdrive keeps its own encrypted copy for connection-time use; Secrets Manager is where the value is owned, versioned, audited, and rotated from.
Secret name: adventive-db-<db>-<mode>-<env>, lowercase and hyphenated, matching the adventive-<domain>-… convention already used for adventive-idp-recovery-*.
Secret value (JSON): the shape the infra/cloudflare-hyperdrive/ module already writes, unchanged.
{ "username": "hd_console_ro", "password": "…", "host": "production.cluster-ro-coi6rcntfbgg.us-east-1.rds.amazonaws.com", "port": 3306, "database": "console"}The host field records the actual RDS/Aurora endpoint the credential is meant for, the writer endpoint for a rw secret, the reader endpoint for a production ro secret. Examples: adventive-db-console-ro-dev, adventive-db-aggregate-rw-prd, adventive-db-billing-ro-prd. For a production billing secret the host is the production cluster endpoint (shared with console).
This is distinct from Cloudflare Secrets Store, which remains the home for Worker runtime secrets such as the New Relic license key. Hyperdrive origin credentials are configuration on the Hyperdrive resource, not Worker-bound secrets, and are never set with wrangler secret put.
Tunnel origin hostnames
Section titled “Tunnel origin hostnames”Hyperdrive connects to a public hostname that Cloudflare Access protects and cloudflared proxies to the private database endpoint. The hostname tracks the endpoint, not the access mode, because read-only and read-write connections to the same endpoint differ only by MySQL user.
Single-endpoint environments (dev, stg). One hostname per database; the ro and rw Hyperdrive configs both point at it and differ only by user.
db-console-dev.adventive.dev,db-aggregate-dev.adventive.dev,db-billing-dev.adventive.devdb-console-stg.adventivestg.com,db-aggregate-stg.adventivestg.com,db-billing-stg.adventivestg.com
Multi-endpoint environment (prd). Two hostnames per database, one per Aurora endpoint, so read-only traffic reaches the replicas. billing gets its own hostnames even though they resolve to the same production-cluster endpoints as console, keeping the per-database naming uniform.
| Hostname | cloudflared ingress target |
|---|---|
db-console-rw-prd.adventive.com | production.cluster-coi6rcntfbgg.us-east-1.rds.amazonaws.com:3306 (writer) |
db-console-ro-prd.adventive.com | production.cluster-ro-coi6rcntfbgg.us-east-1.rds.amazonaws.com:3306 (reader) |
db-billing-rw-prd.adventive.com | production.cluster-coi6rcntfbgg.us-east-1.rds.amazonaws.com:3306 (writer, shared with console) |
db-billing-ro-prd.adventive.com | production.cluster-ro-coi6rcntfbgg.us-east-1.rds.amazonaws.com:3306 (reader, shared with console) |
db-aggregate-rw-prd.adventive.com | aggregate.cluster-coi6rcntfbgg.us-east-1.rds.amazonaws.com:3306 (writer) |
db-aggregate-ro-prd.adventive.com | aggregate.cluster-ro-coi6rcntfbgg.us-east-1.rds.amazonaws.com:3306 (reader) |
The existing dev hostnames (db-console-dev.adventive.dev, db-aggregate-dev.adventive.dev, db-billing-dev.adventive.dev) already match the single-endpoint pattern, so no dev hostname changes. If a read replica is later added in dev or staging, the read-only configs move to a new -ro hostname without any rename elsewhere.
Hyperdrive configs
Section titled “Hyperdrive configs”Per-role connectors use the resource-type prefix adv-hd- (Hyperdrive) followed by <db>-<mode>-<env>. A Hyperdrive config is shared infrastructure bound by ID, so it is named for what it is — a Hyperdrive config for one database role — rather than for any one consuming Worker.
Config name: adv-hd-<db>-<mode>-<env>, eighteen configs for console, aggregate, and billing across three environments.
adv-hd-console-ro-dev adv-hd-console-ro-stg adv-hd-console-ro-prdadv-hd-console-rw-dev adv-hd-console-rw-stg adv-hd-console-rw-prdadv-hd-aggregate-ro-dev adv-hd-aggregate-ro-stg adv-hd-aggregate-ro-prdadv-hd-aggregate-rw-dev adv-hd-aggregate-rw-stg adv-hd-aggregate-rw-prdadv-hd-billing-ro-dev adv-hd-billing-ro-stg adv-hd-billing-ro-prdadv-hd-billing-rw-dev adv-hd-billing-rw-stg adv-hd-billing-rw-prdA Hyperdrive config is a shared resource: any Worker binds it by ID, so the adv-hd- prefix names the resource type, not an owning project. The three legacy single-user configs — adv-svc-public-api-console-dev, adv-svc-public-api-aggregate-dev, and adv-svc-public-api-billing-dev, each carrying a full-access DB user (conn-limit 60) — were superseded by the -ro/-rw pairs and have since been retired. The public API Worker now binds the read-only adv-hd-*-ro connectors. 02 covers the cutover.
Worker bindings
Section titled “Worker bindings”Bindings are SCREAMING_SNAKE_CASE with no environment suffix, each [env.*] block in wrangler.toml points the same binding name at that environment’s Hyperdrive ID.
| Binding | Bound to (per env) |
|---|---|
DB_CONSOLE_RO | adv-hd-console-ro-<env> |
DB_CONSOLE_RW | adv-hd-console-rw-<env> |
DB_AGGREGATE_RO | adv-hd-aggregate-ro-<env> |
DB_AGGREGATE_RW | adv-hd-aggregate-rw-<env> |
DB_BILLING_RO | adv-hd-billing-ro-<env> |
DB_BILLING_RW | adv-hd-billing-rw-<env> |
A Worker binds only the modes it uses. A read-only service binds DB_CONSOLE_RO and nothing else, so the read-write credential is never even present in its runtime, a compromised read path cannot write. The public API Worker is read-path: its DB_CONSOLE / DB_AGGREGATE bindings now resolve to the read-only adv-hd-*-ro connectors, and adopt the explicit _RO binding names as they are renamed. A read-only service never holds a write credential at runtime.
The full matrix
Section titled “The full matrix”One row per (database, mode, environment). Every name in a row is derivable from its first three columns.
| DB | Mode | Env | MySQL user | Secret | Origin hostname | Hyperdrive config | Binding |
|---|---|---|---|---|---|---|---|
| console | ro | dev | hd_console_ro | adventive-db-console-ro-dev | db-console-dev.adventive.dev | adv-hd-console-ro-dev | DB_CONSOLE_RO |
| console | rw | dev | hd_console_rw | adventive-db-console-rw-dev | db-console-dev.adventive.dev | adv-hd-console-rw-dev | DB_CONSOLE_RW |
| console | ro | stg | hd_console_ro | adventive-db-console-ro-stg | db-console-stg.adventivestg.com | adv-hd-console-ro-stg | DB_CONSOLE_RO |
| console | rw | stg | hd_console_rw | adventive-db-console-rw-stg | db-console-stg.adventivestg.com | adv-hd-console-rw-stg | DB_CONSOLE_RW |
| console | ro | prd | hd_console_ro | adventive-db-console-ro-prd | db-console-ro-prd.adventive.com | adv-hd-console-ro-prd | DB_CONSOLE_RO |
| console | rw | prd | hd_console_rw | adventive-db-console-rw-prd | db-console-rw-prd.adventive.com | adv-hd-console-rw-prd | DB_CONSOLE_RW |
| aggregate | ro | dev | hd_aggregate_ro | adventive-db-aggregate-ro-dev | db-aggregate-dev.adventive.dev | adv-hd-aggregate-ro-dev | DB_AGGREGATE_RO |
| aggregate | rw | dev | hd_aggregate_rw | adventive-db-aggregate-rw-dev | db-aggregate-dev.adventive.dev | adv-hd-aggregate-rw-dev | DB_AGGREGATE_RW |
| aggregate | ro | stg | hd_aggregate_ro | adventive-db-aggregate-ro-stg | db-aggregate-stg.adventivestg.com | adv-hd-aggregate-ro-stg | DB_AGGREGATE_RO |
| aggregate | rw | stg | hd_aggregate_rw | adventive-db-aggregate-rw-stg | db-aggregate-stg.adventivestg.com | adv-hd-aggregate-rw-stg | DB_AGGREGATE_RW |
| aggregate | ro | prd | hd_aggregate_ro | adventive-db-aggregate-ro-prd | db-aggregate-ro-prd.adventive.com | adv-hd-aggregate-ro-prd | DB_AGGREGATE_RO |
| aggregate | rw | prd | hd_aggregate_rw | adventive-db-aggregate-rw-prd | db-aggregate-rw-prd.adventive.com | adv-hd-aggregate-rw-prd | DB_AGGREGATE_RW |
| billing | ro | dev | hd_billing_ro | adventive-db-billing-ro-dev | db-billing-dev.adventive.dev | adv-hd-billing-ro-dev | DB_BILLING_RO |
| billing | rw | dev | hd_billing_rw | adventive-db-billing-rw-dev | db-billing-dev.adventive.dev | adv-hd-billing-rw-dev | DB_BILLING_RW |
| billing | ro | stg | hd_billing_ro | adventive-db-billing-ro-stg | db-billing-stg.adventivestg.com | adv-hd-billing-ro-stg | DB_BILLING_RO |
| billing | rw | stg | hd_billing_rw | adventive-db-billing-rw-stg | db-billing-stg.adventivestg.com | adv-hd-billing-rw-stg | DB_BILLING_RW |
| billing | ro | prd | hd_billing_ro | adventive-db-billing-ro-prd | db-billing-ro-prd.adventive.com | adv-hd-billing-ro-prd | DB_BILLING_RO |
| billing | rw | prd | hd_billing_rw | adventive-db-billing-rw-prd | db-billing-rw-prd.adventive.com | adv-hd-billing-rw-prd | DB_BILLING_RW |
Security and resiliency rationale
Section titled “Security and resiliency rationale”Because this is a Cloudflare design standard, it is measured against the six platform pillars.
| Pillar | How the standard addresses it |
|---|---|
| Redundancy | Production read-only traffic targets the Aurora reader endpoint, spreading reads across replicas and keeping the writer for writes. |
| Resiliency | Read-only and read-write are separate MySQL users bound separately; a compromised or buggy read path holds no write grant, so its blast radius is read-only. |
| Disaster recovery | Every credential’s source of truth is AWS Secrets Manager, out-of-band from Cloudflare, so a Cloudflare-side incident does not lock the credentials away. |
| Backup | Secrets Manager versions every credential; the previous version is retained across rotation for rollback. |
| Deployment | Configs, secrets, and Access apps are provisioned by the infra/cloudflare-hyperdrive/ Terraform module and promoted dev → stg → prd; see 02. |
| Observability | One config per (db, mode, env) means connection metrics and logs attribute cleanly to a single database, environment, and access mode. |
See also: Credential provisioning · Workers naming conventions · AWS Secrets Manager