TinyShip
TinyShip
 TinyShip
TinyShip
TinyShip Documentation
TinyShip User GuideGetting StartedBasic Configuration
Credits System Configuration
Storage Service ConfigurationCaptcha Configuration
DeploymentCloud Platform DeploymentCloudflare Workers DeploymentDokploy DeploymentDocker DeploymentTraditional Deployment
Development Best PracticesLocal E2E Workflow
User GuideDeployment

Cloudflare Workers Deployment

Guide to deploying TanStack Start app to Cloudflare Workers

Prerequisites

  • Have a Cloudflare account
  • Dependencies are installed (wrangler and @cloudflare/vite-plugin are already in devDependencies)

Step 1: Log in to Cloudflare

cd apps/tanstack-app
npx wrangler login

This will open a browser for authorization. After success, the terminal shows Successfully logged in.

Step 2: Configure Hyperdrive (Database)

First, create Hyperdrive with your PostgreSQL connection string (this proxy is used by online Workers):

npx wrangler hyperdrive create tinyship-db \
  --connection-string="postgresql://user:password@host:5432/dbname"

After creation, you will get a Hyperdrive ID. Then configure both fields in wrangler.jsonc:

  • id: used for production deployment (Cloudflare edge accesses DB via Hyperdrive after wrangler deploy)
  • localConnectionString: used for local development (wrangler dev / pnpm dev:cf connects directly to your local/LAN DB)

Example (matching current project structure):

"hyperdrive": [
  {
    "binding": "HYPERDRIVE",
    "id": "<your-hyperdrive-id>",
    "localConnectionString": "postgresql://viking:unused@localhost:5432/shipeasy_dev"
  }
]

Notes:

  • Local debugging prefers localConnectionString, which is easier for local DB access and avoids depending on remote network.
  • After deploying to Cloudflare, localConnectionString is not used; the id Hyperdrive config is used.
  • If localConnectionString is not set, local CF debugging goes through remote Hyperdrive path, which is usually slower and more internet-dependent.

Step 3: Configure Secrets

Sensitive configuration in Cloudflare Workers should use Secrets (not .env):

# Required
npx wrangler secret put BETTER_AUTH_SECRET
npx wrangler secret put DATABASE_URL

# Add more secrets as needed

# 2) You can also bulk import from a file
npx wrangler secret bulk .secrets.json

Recommendation: use .secrets.json only for local temporary import, and do not commit it to Git.

Non-sensitive variables should be put in vars in wrangler.jsonc:

"vars": {
  "APP_BASE_URL": "https://your-domain.com",
  "BETTER_AUTH_URL": "https://your-domain.com"
}

Step 4: Local Preview

Validate first in local Workers simulation:

cd apps/tanstack-app
pnpm dev:cf

This command runs Vite + Cloudflare plugin with CF_DEPLOY=1, simulating Workers runtime. Recommended checks:

  1. The app opens on the output URL (usually http://localhost:7001)
  2. Sign in / sign up works
  3. DB-dependent features load correctly
  4. API endpoints return expected responses

Step 5: Deploy to Production

cd apps/tanstack-app
pnpm run deploy:cf

This runs CF_DEPLOY=1 vite build && wrangler deploy. On success, it prints an address like:

https://tinyship-tanstack.<your-subdomain>.workers.dev

Step 6: Post-deploy Verification

Verify these endpoints on deployed URL:

CheckURLExpected
Health check/api/health200 OK
Home/enPage renders normally
Sign-in page/en/signinPage is accessible
DB feature/api/credits/balance (requires session)Returns balance correctly
# Quick smoke test
curl -s -o /dev/null -w "%{http_code}" https://your-worker-url/api/health

How CF Mode Works (Developer Notes)

Cloudflare integration uses an opt-in approach and does not affect normal development:

┌─────────────────────────────────────────────────┐
│  pnpm dev          (normal dev)                 │
│  → Vite dev server, Node.js, DATABASE_URL       │
│  → CF_DEPLOY is not set                          │
│  → cloudflare() plugin is not loaded             │
├─────────────────────────────────────────────────┤
│  pnpm dev:cf       (CF local preview)            │
│  → CF_DEPLOY=1 → load cloudflare() plugin        │
│  → Vite + Cloudflare plugin simulates Workers    │
│  → Uses Hyperdrive or DATABASE_URL               │
├─────────────────────────────────────────────────┤
│  pnpm run deploy:cf (production deploy)          │
│  → CF_DEPLOY=1 → load cloudflare() plugin        │
│  → vite build → workers-compatible output        │
│  → wrangler deploy → publish to edge network     │
└─────────────────────────────────────────────────┘

Key mechanism: vite.config.ts checks process.env.CF_DEPLOY, and dynamically imports @cloudflare/vite-plugin only when present. This means:

  • pnpm dev / pnpm build: pure Vite/Node.js flow, no CF overhead
  • pnpm dev:cf / pnpm run deploy:cf: Workers-compatible build flow

Comparison with Other Deployment Options

FeatureCloudflare WorkersDockerVercelTraditional
Supported frameworkTanStack StartAllNext.jsAll
Cold start< 5msNone (always-on)~250msNone
Global distributionAutomaticManualAutomaticManual
Free quota100k requests/dayNoneLimitedNone
Database supportHyperdrive requiredNative TCPNative TCPNative TCP
Upload limit100MB / 500MBUnlimited50MBUnlimited
Ops costVery lowMediumLowHigh

Cloudflare Workers is great for scenarios requiring high performance, global coverage, and low ops cost. If you're concerned about DB connectivity model or runtime limits, Docker or traditional deployment may be simpler.

Cloud Platform Deployment

Deploy to Vercel, Netlify, Railway and other cloud platforms

Dokploy Deployment

Deploy TinyShip with Dokploy on your own server

On this page

PrerequisitesStep 1: Log in to CloudflareStep 2: Configure Hyperdrive (Database)Step 3: Configure SecretsStep 4: Local PreviewStep 5: Deploy to ProductionStep 6: Post-deploy VerificationHow CF Mode Works (Developer Notes)Comparison with Other Deployment Options