Deploy to Cloudflare Workers with D1 or Postgres + Hyperdrive

Run a ShipAny (TanStack Start) SaaS on Cloudflare Workers — D1 for zero infrastructure, or your existing Postgres through Hyperdrive. Setup, verification and the pitfalls we hit migrating shipany.ai.

Last updated: Oct 8, 2026

shipany.ai itself runs on Cloudflare Workers: a ShipAny TanStack app talking to an existing Postgres database through Hyperdrive. This page covers both supported setups, how to deploy, and the pitfalls we hit during that migration.

Two database options

D1Postgres + Hyperdrive
Best forNew projects, zero external infrastructureYou already have Postgres (RDS, Neon, Supabase, self-hosted) or need Postgres features
Bindingd1_databases → DBhyperdrive → HYPERDRIVE
Schemawrangler d1 migrations apply --remotepnpm db:migrate straight against Postgres (not through Hyperdrive)
BundlePostgres driver stubbed outPostgres driver kept

The backend is selected by vars.DATABASE_PROVIDER in wrangler.jsonc (d1 or postgresql); the build reads it to decide which driver goes into the Worker bundle.

Deploying

The template includes a deploy-cloudflare agent skill that automates all of this. By hand, the steps are:

  1. Create the database binding — npx wrangler d1 create <name>, or for Postgres npx wrangler hyperdrive create <name> --connection-string="postgres://…".
  2. Fill in wrangler.jsonc — worker name, an explicit compatibility_date, nodejs_compat, vars (DATABASE_PROVIDER, VITE_APP_URL, VITE_APP_NAME) and the binding from step 1.
  3. Set secrets — npx wrangler secret put AUTH_SECRET (and CONFIG_ENCRYPTION_KEY if you encrypt settings).
  4. Put public build-time values in .env.production — VITE_APP_URL is baked into the bundle at build time.
  5. Deploy — pnpm run cf:deploy loads .env.production, builds with the cloudflare_module preset and runs wrangler deploy.

Moving an existing domain with zero downtime

If your site already runs elsewhere behind Cloudflare DNS, you don't need to touch DNS at all. Add a Worker Route for example.com/*; the Worker intercepts traffic before it reaches the old origin. To roll back, delete the route — traffic goes back to the old origin within seconds. Keep the old deployment running until you've verified payments and sign-in.

Pitfalls we hit

  • Can't set compatibility date in the future — the build fills in your machine's local date. In timezones ahead of UTC this can be "tomorrow" for Cloudflare. Set compatibility_date explicitly.
  • Admin settings silently missing with Hyperdrive — with Hyperdrive there's no DATABASE_URL, and an older settings loader treated that as "no database" and returned empty settings. Pages still rendered, but payment and OAuth providers were missing ("No payment provider configured"). Make sure your settings loader recognizes the HYPERDRIVE binding.
  • Turn off Hyperdrive's query cache for transactional apps — by default it caches reads for up to 60 seconds, so order status, credit balances or settings can look stale. The connection pool, not the cache, is what makes Hyperdrive fast: npx wrangler hyperdrive update <id> --caching-disabled=true.
  • Reusing a production database? Don't run migrations. If the tables were created by another system, Drizzle's migration journal is empty and db:migrate would try to create everything from scratch.
  • Keep AUTH_SECRET identical to your previous deployment, or every user gets signed out.

Verify after every deploy

A green status code isn't enough. Check that:

  1. The homepage's /assets/* files match your new build (so traffic really reaches the Worker).
  2. /api/config/public returns your configured switches (stripe_enabled, google_auth_enabled, …), identical to the previous deployment.
  3. Database connections arrive from Cloudflare IP ranges (Hyperdrive), and npx wrangler tail shows no exceptions.
  4. Sign-in and one real payment per provider work end to end.

Related reading

More in Integrations

Ship your AI SaaS with ShipAny

Auth, payments, credits, i18n and admin are pre-wired — start from a production-ready template and focus on your product.