Skip to content

Environment Management Guide for Multi-Worker Microservices

Best Practices for Cloudflare Workers & Pages Architecture

Goal: Zero Duck Hunting

This guide eliminates confusion about environments, deployments, and service bindings across multiple workers.


Table of Contents

  1. Environment Strategy
  2. Naming Conventions
  3. Service Binding Configuration
  4. Deployment Workflows
  5. Environment Variables
  6. Custom Domains
  7. Troubleshooting
  8. Quick Reference

Environment Strategy

Three-Tier Architecture

Local Development → Preview/Staging → Production
EnvironmentPurposeBranchDomain Pattern
LocalDevelopment & Testingmain (local)localhost:8787
Preview/StagingIntegration Testingmain (preview)preview.stratiqx.ai
ProductionLive Systemmain (production)stratiqx.ai, auth.stratiqx.ai

Naming Conventions

Worker Service Names

Format: {service-name}-{environment}

✅ CORRECT:
- stratiqx-identity-server-dev
- stratiqx-identity-server-prod
- stratiqx-payment-dev  
- stratiqx-payment-prod
- stratiqx-communication-dev
- stratiqx-communication-prod

❌ INCORRECT:
- stratiqx-identity-server (ambiguous)
- identity-prod (inconsistent prefix)
- payment-service-production (too verbose)

Pages Project Names

Format: {project-name}

✅ CORRECT:
- strategic-intelligence-onboarding
- strategic-intelligence-dashboard

❌ INCORRECT:
- strategic-intelligence-onboarding-prod (redundant)

Custom Domains

Pattern: {subdomain}.stratiqx.ai

✅ PRODUCTION:
- auth.stratiqx.ai → stratiqx-identity-server-prod
- payments.stratiqx.ai → stratiqx-payment-prod
- api.stratiqx.ai → stratiqx-communication-prod

✅ PREVIEW/STAGING:
- preview.stratiqx.ai → Pages Preview Environment
- dev-auth.stratiqx.ai → stratiqx-identity-server-dev
- dev-payments.stratiqx.ai → stratiqx-payment-dev

Service Binding Configuration

Standard wrangler.toml Pattern

toml
name = "your-service-name"
compatibility_date = "2024-01-01"

# TOP-LEVEL = PRODUCTION DEFAULTS
# Always configure top-level bindings for production
[[services]]
binding = "AUTH_SERVICE"
service = "stratiqx-identity-server-prod"

[[services]]
binding = "PAYMENT_SERVICE"
service = "stratiqx-payment-prod"

[[services]]
binding = "COMMUNICATION_SERVICE"
service = "stratiqx-communication-prod"

[vars]
NODE_ENV = "production"

# PREVIEW ENVIRONMENT
[env.preview]
name = "your-service-name-preview"

[[env.preview.services]]
binding = "AUTH_SERVICE"
service = "stratiqx-identity-server-dev"  # Use dev services for testing

[[env.preview.services]]
binding = "PAYMENT_SERVICE"
service = "stratiqx-payment-dev"

[[env.preview.services]]
binding = "COMMUNICATION_SERVICE"
service = "stratiqx-communication-dev"

[env.preview.vars]
NODE_ENV = "preview"

# PRODUCTION ENVIRONMENT (explicit)
[env.production]
name = "your-service-name"

[[env.production.services]]
binding = "AUTH_SERVICE"
service = "stratiqx-identity-server-prod"

[[env.production.services]]
binding = "PAYMENT_SERVICE"
service = "stratiqx-payment-prod"

[[env.production.services]]
binding = "COMMUNICATION_SERVICE"
service = "stratiqx-communication-prod"

[env.production.vars]
NODE_ENV = "production"

Pages Function Service Binding Proxy

Create functions/api/{service}/[[path]].ts for each service:

typescript
// functions/api/payment/[[path]].ts
export async function onRequest(context: any) {
  const { request, env } = context;
  const url = new URL(request.url);
  const servicePath = url.pathname.replace('/api/payment', '');
  
  // Create service request
  const serviceRequest = new Request(
    `https://internal${servicePath}${url.search}`,
    {
      method: request.method,
      headers: request.headers,
      body: request.body,
    }
  );

  // Use service binding if available, fallback to HTTP
  if (env.PAYMENT_SERVICE) {
    console.log('Using PAYMENT_SERVICE binding for:', servicePath);
    return await env.PAYMENT_SERVICE.fetch(serviceRequest);
  } else {
    console.log('PAYMENT_SERVICE binding not available - using HTTP fallback');
    const fallbackUrl = `https://payments.stratiqx.ai${servicePath}${url.search}`;
    return await fetch(fallbackUrl, {
      method: request.method,
      headers: request.headers,
      body: request.body,
    });
  }
}

Deployment Workflows

Understanding Pages Deployments

Deployment CommandEnvironmentBranchUse Case
wrangler pages deployProductionmainLive releases
wrangler pages deploy --branch featurePreviewfeatureFeature testing
wrangler pages deploy --branch mainPreviewmainStaging testing

Deployment Checklist

For Workers:

bash
# 1. Deploy to development environment
wrangler deploy --env preview

# 2. Test in preview environment
# Run integration tests, verify service bindings

# 3. Deploy to production environment  
wrangler deploy --env production

# 4. Verify production deployment
wrangler tail --env production

For Pages:

bash
# 1. Deploy to preview for testing
wrangler pages deploy --branch staging

# 2. Test preview deployment
# Verify all service integrations work

# 3. Deploy to production (main branch)
wrangler pages deploy

# 4. Verify production custom domain
curl https://preview.stratiqx.ai/health

Environment Variables

Frontend (.env patterns)

.env.local (Development)

bash
VITE_NODE_ENV=development
VITE_IDENTITY_API_URL=http://127.0.0.1:8787
# Leave VITE_PAYMENT_API_URL unset to use service bindings

.env.production (Production)

bash
VITE_NODE_ENV=production
VITE_IDENTITY_API_URL=https://auth.stratiqx.ai
# Leave VITE_PAYMENT_API_URL unset to force service bindings
VITE_STRIPE_PUBLISHABLE_KEY=pk_live_...

Service Configuration Logic

typescript
// Frontend service configuration
constructor() {
  const paymentApiUrl = import.meta.env.VITE_PAYMENT_API_URL;
  
  if (!paymentApiUrl || paymentApiUrl === '') {
    // Force service bindings when no external URL specified
    this.baseURL = '/api/payment';
    console.log('Using service bindings via /api/payment');
  } else {
    // Use external URL (for local development)
    this.baseURL = paymentApiUrl;
    console.log('Using external API:', paymentApiUrl);
  }
}

Custom Domains

Domain Mapping Strategy

Production Services:
├── auth.stratiqx.ai → stratiqx-identity-server-prod
├── payments.stratiqx.ai → stratiqx-payment-prod  
├── api.stratiqx.ai → stratiqx-communication-prod
└── preview.stratiqx.ai → Pages Production Environment

Development/Staging:
├── dev-auth.stratiqx.ai → stratiqx-identity-server-dev
├── dev-payments.stratiqx.ai → stratiqx-payment-dev
└── dev-api.stratiqx.ai → stratiqx-communication-dev

Domain Configuration Commands

bash
# Add custom domain to worker
wrangler custom-domains add auth.stratiqx.ai

# Add custom domain to pages
wrangler pages domain add preview.stratiqx.ai

Troubleshooting

Common Issues & Solutions

Issue: "Service binding not found"

Symptoms: HTTP calls instead of service bindings Solution:

  1. Check wrangler.toml service names match exactly
  2. Verify environment deployment (preview vs production)
  3. Ensure Pages Function proxy exists

Issue: "Environment mismatch"

Symptoms: Production showing as Preview Solution:

  1. Deploy to main branch without --branch flag
  2. Check Cloudflare dashboard environment settings
  3. Verify wrangler.toml environment configuration

Issue: "CORS errors in development"

Symptoms: Frontend can't reach local workers Solution:

  1. Add CORS headers to workers
  2. Use wrangler dev --local --port 8787
  3. Set VITE_*_API_URL for local development

Issue: "Custom domain not working"

Symptoms: Domain shows 404 or old deployment Solution:

  1. Check DNS propagation: dig preview.stratiqx.ai
  2. Verify domain is added to correct service
  3. Wait for SSL certificate provisioning (up to 24h)

Debug Commands

bash
# Check deployment status
wrangler pages deployment list

# View environment variables
wrangler pages secret list

# Monitor worker logs
wrangler tail --env production --format pretty

# Check service binding status
wrangler dev --local --inspect

Quick Reference

Service Naming Quick Check

bash
# Current StratIQX Services:
 stratiqx-identity-server-dev
 stratiqx-identity-server-prod  
 stratiqx-payment-dev
 stratiqx-payment-prod
 stratiqx-communication-dev
 stratiqx-communication-prod

# Pages Projects:
 strategic-intelligence-onboarding

Environment Variables Checklist

  • [ ] .env.production has no VITE_PAYMENT_API_URL (forces service bindings)
  • [ ] wrangler.toml top-level uses -prod services
  • [ ] env.preview uses -dev services for testing
  • [ ] All service binding names are consistent

Deployment Checklist

  • [ ] Workers deployed to both --env preview and --env production
  • [ ] Pages deployed to both preview (with --branch) and production (without)
  • [ ] Custom domains point to correct services
  • [ ] Service bindings tested in both environments

Success Metrics

When properly configured, you should see:

In Browser Network Tab:

✅ /api/payment/confirm-payment (service binding)
✅ /api/auth/validate (service binding)  
❌ https://payments.stratiqx.ai/* (external HTTP - avoid this)

In Worker Logs:

✅ "Using SERVICE_NAME binding for: /endpoint"
❌ "SERVICE_NAME binding not available - using HTTP fallback"

In Frontend Console:

✅ "Using service bindings via /api/payment"
❌ "Using external API: https://payments.stratiqx.ai"

Emergency Recovery

If environments get mixed up:

  1. Immediate Fix:

    bash
    # Force correct service bindings
    wrangler pages deploy --compatibility-date 2024-01-01
  2. Full Reset:

    bash
    # Redeploy all services
    cd stratiqx-identity-server && wrangler deploy --env production
    cd stratiqx-payment && wrangler deploy --env production  
    cd stratiqx-communication && wrangler deploy --env production
    cd strategic-intelligence-onboarding && wrangler pages deploy
  3. Verify Recovery:

    bash
    curl https://preview.stratiqx.ai/health
    wrangler pages deployment list | head -5

Remember: When in doubt, check the service binding logs first!

Last updated: August 26, 2025

Strategic Intelligence Hub Documentation