Skip to content

Staging Deployment

Staging is your production dress rehearsal. It’s where you validate that everything works correctly before going live. This guide walks you through setting up and deploying to a staging environment.

Why Staging Matters

flowchart LR
  A["Local Development"] --> B["Staging"]
  B --> C["Production"]

  B -.-> |"Catch bugs here"| B
  B -.-> |"Test migrations"| B
  B -.-> |"Validate API"| B

Staging gives you a production-like environment for:

  • Testing migrations before they touch production data
  • Validating API behavior with real Cloudflare infrastructure
  • Catching configuration issues that don’t appear locally
  • Team testing without affecting production users

Prerequisites

Before deploying to staging, ensure you have:

  1. Cloudflare account with D1 access
  2. Authenticated Wrangler (pnpm wrangler login)
  3. Environment configured in wrangler.toml (see Environment Configuration)

Step 1: Create the Staging Database

First, create a D1 database for your staging environment.

Creating the Database

Terminal
pnpm wrangler d1 create d1-migration-mastery-staging

Expected output:

✅ Successfully created DB 'd1-migration-mastery-staging' in region WNAM
Created your new D1 database.
[[d1_databases]]
binding = "DB"
database_name = "d1-migration-mastery-staging"
database_id = "f1e2d3c4-b5a6-0987-fedc-ba0987654321"

Adding to wrangler.toml

Copy the database configuration to your wrangler.toml:

wrangler.toml
# Staging Environment
[env.staging]
name = "d1-migration-mastery-staging"
[[env.staging.d1_databases]]
binding = "DB"
database_name = "d1-migration-mastery-staging"
database_id = "f1e2d3c4-b5a6-0987-fedc-ba0987654321"
migrations_dir = "migrations"

Verifying the Database

Confirm your database was created:

Terminal
pnpm wrangler d1 list

Expected output:

┌───────────────────────────────┬──────────────────────────────────────┬────────┐
│ Name │ ID │ Region │
├───────────────────────────────┼──────────────────────────────────────┼────────┤
│ d1-migration-mastery-staging │ f1e2d3c4-b5a6-0987-fedc-ba0987654321 │ WNAM │
└───────────────────────────────┴──────────────────────────────────────┴────────┘

Step 2: Run Staging Migrations

With the database created, apply your migrations to set up the schema.

Checking Migration Status

Before applying, check what migrations are pending:

Terminal
pnpm wrangler d1 migrations list DB --remote --env staging

Expected output (first deployment):

Migrations:
┌─────────────────────────────────────┬────────────────────┐
│ name │ status │
├─────────────────────────────────────┼────────────────────┤
│ 0000_initial.sql │ ⏳ Pending │
├─────────────────────────────────────┼────────────────────┤
│ 0001_add_user_profile.sql │ ⏳ Pending │
├─────────────────────────────────────┼────────────────────┤
│ 0002_add_posts.sql │ ⏳ Pending │
└─────────────────────────────────────┴────────────────────┘

Applying Migrations

Apply all pending migrations to staging:

Terminal
pnpm wrangler d1 migrations apply DB --remote --env staging

Expected output:

Migrations to be applied:
┌─────────────────────────────────────┐
│ name │
├─────────────────────────────────────┤
│ 0000_initial.sql │
├─────────────────────────────────────┤
│ 0001_add_user_profile.sql │
├─────────────────────────────────────┤
│ 0002_add_posts.sql │
└─────────────────────────────────────┘
✔ About to apply 3 migration(s)
Your database may not be available to serve requests during the migration, continue? … yes
🌀 Executing on remote database DB (f1e2d3c4-b5a6-0987-fedc-ba0987654321):
Applying migration: 0000_initial.sql
Running query 1/2: CREATE TABLE `users`...
✔ Query 1/2 succeeded
Running query 2/2: CREATE UNIQUE INDEX...
✔ Query 2/2 succeeded
✔ Applied 0000_initial.sql
Applying migration: 0001_add_user_profile.sql
Running query 1/1: ALTER TABLE `users`...
✔ Query 1/1 succeeded
✔ Applied 0001_add_user_profile.sql
Applying migration: 0002_add_posts.sql
Running query 1/2: CREATE TABLE `posts`...
✔ Query 1/2 succeeded
Running query 2/2: CREATE INDEX...
✔ Query 2/2 succeeded
✔ Applied 0002_add_posts.sql
✅ 3 migration(s) applied successfully

Verifying Applied Migrations

Confirm all migrations were applied:

Terminal
pnpm wrangler d1 migrations list DB --remote --env staging

Expected output (after applying):

Migrations:
┌─────────────────────────────────────┬────────────────────┐
│ name │ status │
├─────────────────────────────────────┼────────────────────┤
│ 0000_initial.sql │ ✅ Applied │
├─────────────────────────────────────┼────────────────────┤
│ 0001_add_user_profile.sql │ ✅ Applied │
├─────────────────────────────────────┼────────────────────┤
│ 0002_add_posts.sql │ ✅ Applied │
└─────────────────────────────────────┴────────────────────┘

Step 3: Deploy the Application

With the database ready, deploy your Worker to staging.

Deploying to Staging

Terminal
pnpm wrangler deploy --env staging

Expected output:

⛅️ wrangler 3.x.x
-------------------
Your worker has access to the following bindings:
- D1 Databases:
- DB: d1-migration-mastery-staging (f1e2d3c4-b5a6-0987-fedc-ba0987654321)
Total Upload: 150.23 KiB / gzip: 35.67 KiB
Worker Startup Time: 15 ms
Uploaded d1-migration-mastery-staging (2.50 sec)
Published d1-migration-mastery-staging (0.35 sec)
https://d1-migration-mastery-staging.<your-subdomain>.workers.dev
Current Deployment ID: abc123-def456-ghi789
Current Version ID: xyz789-abc123-def456

Your staging environment is now live at the URL shown in the output.

Step 4: Testing with Swagger

The Swagger UI provides an interactive way to test your API endpoints on staging.

Accessing Swagger

Navigate to your staging Swagger UI:

https://d1-migration-mastery-staging.<your-subdomain>.workers.dev/swagger

Replace <your-subdomain> with your actual Cloudflare Workers subdomain.

Testing CRUD Operations

Use Swagger to verify your API works correctly:

flowchart TD
  A["Open Swagger UI"] --> B["Test GET /users"]
  B --> C{Returns empty array?}
  C -->|Yes| D["Test POST /users"]
  D --> E["Test GET /users again"]
  E --> F{Returns created user?}
  F -->|Yes| G["Test PUT /users/:id"]
  G --> H["Test DELETE /users/:id"]
  H --> I["✅ All tests pass"]

  C -->|No - Error| J["Check migrations applied"]
  F -->|No - Error| K["Check database binding"]

1. Test listing users (should be empty initially):

  • Expand GET /users
  • Click “Try it out”
  • Click “Execute”
  • Verify response: [] (empty array)

2. Create a test user:

  • Expand POST /users
  • Click “Try it out”
  • Enter request body:
    {
    "email": "staging-test@example.com",
    "name": "Staging Tester"
    }
  • Click “Execute”
  • Verify response includes the created user with an ID

3. Verify the user was created:

  • Expand GET /users
  • Click “Execute”
  • Verify response includes the created user

4. Test updating the user:

  • Expand PUT /users/{id}
  • Enter the user ID from step 2
  • Enter updated data:
    {
    "name": "Updated Staging Tester"
    }
  • Click “Execute”
  • Verify the name was updated

5. Test deleting the user:

  • Expand DELETE /users/{id}
  • Enter the user ID
  • Click “Execute”
  • Verify successful deletion

Expected Swagger Responses

Successful GET /users response:

[
{
"id": 1,
"email": "staging-test@example.com",
"name": "Staging Tester",
"createdAt": "2024-01-15T10:30:00.000Z"
}
]

Successful POST /users response:

{
"id": 1,
"email": "staging-test@example.com",
"name": "Staging Tester",
"createdAt": "2024-01-15T10:30:00.000Z"
}

Staging Deployment Checklist

Before considering staging deployment complete:

CheckCommand/Action
✅ Database createdpnpm wrangler d1 list
✅ wrangler.toml updatedVerify [env.staging] section
✅ Migrations appliedpnpm wrangler d1 migrations list DB --remote --env staging
✅ Worker deployedpnpm wrangler deploy --env staging
✅ Swagger accessibleVisit /swagger on staging URL
✅ CRUD operations workTest via Swagger UI

Troubleshooting Staging Issues

”Database not found”

Error:

Error: Database DB not found for environment staging

Solution: Ensure your wrangler.toml has the correct staging configuration:

wrangler.toml
[env.staging]
name = "d1-migration-mastery-staging"
[[env.staging.d1_databases]]
binding = "DB"
database_name = "d1-migration-mastery-staging"
database_id = "your-actual-database-id"
migrations_dir = "migrations"

Swagger shows 500 errors

Cause: Usually indicates missing migrations or incorrect database binding.

Solution:

  1. Verify migrations are applied:

    Terminal window
    pnpm wrangler d1 migrations list DB --remote --env staging
  2. Redeploy if needed:

    Terminal window
    pnpm wrangler deploy --env staging
  3. Check Worker logs:

    Terminal window
    pnpm wrangler tail --env staging

Data from local showing in staging

Cause: You may have deployed without the --env staging flag.

Solution: Always use --env staging for staging commands:

Terminal window
# Correct
pnpm wrangler deploy --env staging
pnpm wrangler d1 migrations apply DB --remote --env staging
# Incorrect (affects production!)
pnpm wrangler deploy
pnpm wrangler d1 migrations apply DB --remote

Quick Reference

TaskCommand
Create staging databasepnpm wrangler d1 create <name>
List migrationspnpm wrangler d1 migrations list DB --remote --env staging
Apply migrationspnpm wrangler d1 migrations apply DB --remote --env staging
Deploy to stagingpnpm wrangler deploy --env staging
View staging logspnpm wrangler tail --env staging
Execute SQL on stagingpnpm wrangler d1 execute DB --remote --env staging --command "SELECT * FROM users"

Summary

Deploying to staging involves four main steps:

  1. Create the staging database with wrangler d1 create
  2. Run migrations with wrangler d1 migrations apply --remote --env staging
  3. Deploy the Worker with wrangler deploy --env staging
  4. Test with Swagger to verify everything works

Once you’ve validated your changes on staging, you’re ready to deploy to production with confidence.