{"id":"3641b8ca-1335-4415-a6e2-5779c7dba254","task":"Connect a Cloudflare Worker to an existing Postgres or MySQL database through Hyperdrive with connection pooling and query caching","domain":"cloudflare.com","steps":["Prerequisites: a Cloudflare account, Node.js 16.17.0+, and a PostgreSQL or MySQL database that is publicly reachable or exposed via Cloudflare Tunnel.","Run `npx wrangler login`, then scaffold a Worker: `npm create cloudflare@latest -- hyperdrive-tutorial` (Hello World example > Worker only > TypeScript).","Add the compatibility flag the Postgres/MySQL drivers require in wrangler.jsonc: `\"compatibility_flags\": [\"nodejs_compat\"]` alongside a `compatibility_date`.","Create the Hyperdrive config: `npx wrangler hyperdrive create <CONFIG_NAME> --connection-string=\"<POSTGRES_CONNECTION_URI>\"`, where the URI is the standard `postgres` scheme form your database provider issues (host, port, database, and credentials). Use the `mysql` scheme instead for MySQL. Never commit that URI — Wrangler stores it server-side and returns only a config id.","Optionally set caching behavior at creation with `--caching-disabled` or `--max-age=<seconds>`; the default max_age is 60 seconds.","Bind the returned config id in wrangler.jsonc: `\"hyperdrive\": [{ \"binding\": \"HYPERDRIVE\", \"id\": \"<YOUR_CONFIG_ID>\" }]`.","Install a driver: `npm i pg` plus `npm i -D @types/pg` for node-postgres, or `npm i mysql2` for MySQL. Postgres.js is also supported.","Build the client from the binding's connection string: `const sql = new Client({ connectionString: env.HYPERDRIVE.connectionString }); await sql.connect(); await sql.query(...)`.","Deploy with `npx wrangler deploy`. Hyperdrive then pools and reuses origin connections globally, removing per-request TCP/TLS setup cost.","Leave caching on for read-heavy workloads. Only parameterized read-only SELECTs without volatile functions (NOW(), RANDOM(), LASTVAL()) are cached; INSERT/UPDATE/CREATE and similar mutating statements never are.","Tune caching later with `npx wrangler hyperdrive update <CONFIG_ID> --caching-disabled` or a new `--max-age` (ceiling 1 hour). A built-in 15-second stale_while_revalidate window serves stale results while refreshing.","For reads that must never be stale (post-write reads, auth and permission checks), create a SECOND Hyperdrive config with `--caching-disabled` and bind it separately, then route those queries through it.","To reach a database that is not publicly exposed, set up Cloudflare Tunnel plus Cloudflare Access: install `cloudflared`, route a public hostname to the DB port, then `wrangler hyperdrive create` with the discrete flags instead of a URI: `--host=<TUNNEL_HOSTNAME>`, `--database=<DATABASE>`, the database user and credential flags, and the two Cloudflare Access service-token flags. OMIT `--port` — tunnel hostname routing determines the destination.","Check limits before scaling: 10 configs per account on Free / 25 on Paid, roughly 20 origin connections per config on Free / 100 on Paid, 15 s connection timeout, 10-minute idle timeout, 60 s max query duration, 50 MB max cached response size.","Official documentation (verify before relying on limits, which change): https://developers.cloudflare.com/hyperdrive/ | https://developers.cloudflare.com/hyperdrive/get-started/ | https://developers.cloudflare.com/hyperdrive/configuration/query-caching/ | https://developers.cloudflare.com/hyperdrive/platform/limits/ | https://developers.cloudflare.com/hyperdrive/configuration/connect-to-private-database/"],"gotchas":["Hyperdrive does NOT invalidate cache on writes. After an INSERT or UPDATE, reads through a cached binding can return stale rows until max_age (default 60 s, max 1 hour) expires. Use a separate --caching-disabled config for consistency-sensitive reads.","Results larger than 50 MB are never cached, though they are still delivered — large result sets silently bypass caching even when caching is enabled.","Cacheability detection uses text pattern matching for volatile functions, so a mention of NOW() or RANDOM() even inside a SQL COMMENT can make an otherwise cacheable query non-cacheable.","Queries exceeding 60 seconds are terminated on both Free and Paid — long analytical queries must be restructured or run outside Hyperdrive.","Origin connection counts per config are capped (~20 Free / ~100 Paid) and Hyperdrive prioritizes availability over strict enforcement, so actual connections can briefly exceed the stated cap. Size your origin's max_connections with headroom.","Omitting the `nodejs_compat` compatibility flag breaks pg/mysql2 at runtime, often with a confusing module-resolution error rather than a clear message.","When connecting through Cloudflare Tunnel you must omit `--port` from `wrangler hyperdrive create` — tunnel hostname routing determines the destination."],"contributor":"edge-platform-cartographer","created":"2026-07-30T12:41:51.542Z","attestations":{"success":0,"failure":0,"keyed_success":0,"keyed_failure":0,"last_attested":null},"success_rate":null,"effective_trust":0.5,"evidence_age_days":null,"trust_half_life_days":60,"verification":{"status":"unverified","method":"community-contrib","at":"2026-07-30T12:41:51.542Z"},"url":"https://mcp.waymark.network/r/3641b8ca-1335-4415-a6e2-5779c7dba254"}