Environment Configuration
Overview
Builders International uses multiple environments to ensure code quality and safe deployments. Each environment has specific purposes, access controls, and configurations.
Environment Hierarchy
Development (Local) → Staging → Production
Development Environment
Purpose
Local development and testing on developer machines.
Characteristics
- Access: All developers
- Data: Local/mock data only
- Stability: Unstable, frequent changes
- Deployment: Manual, on-demand
Setup
# Clone repository
git clone https://github.com/Builders-International/project-name.git
cd project-name
# Install dependencies
npm install
# Copy environment template
cp .env.example .env.local
# Configure local environment
# Edit .env.local with local settings
# Start development server
npm run dev
Environment Variables
# .env.local
NODE_ENV=development
API_URL=http://localhost:3000
DATABASE_URL=postgresql://localhost:5432/myapp_dev
LOG_LEVEL=debug
ENABLE_DEBUG_TOOLS=true
# External services (use test/sandbox APIs)
STRIPE_KEY=sk_test_...
SENDGRID_API_KEY=SG.test...
Database
Local PostgreSQL or SQLite:
# Using Docker
docker run -d \
--name postgres-dev \
-p 5432:5432 \
-e POSTGRES_PASSWORD=devpassword \
-e POSTGRES_DB=myapp_dev \
postgres:15
# Run migrations
npm run migrate:dev
# Seed with test data
npm run db:seed
Testing
# Unit tests
npm test
# Watch mode
npm test -- --watch
# Coverage
npm test -- --coverage
# E2E tests (against local server)
npm run test:e2e
Staging Environment
Purpose
Pre-production testing and validation before deploying to production.
Characteristics
- Access: Team + stakeholders
- Data: Sanitized production-like data
- Stability: Stable, updated on merge to main
- Deployment: Automatic via CI/CD
URL Structure
Web: https://staging-project.vercel.app
API: https://staging-api.buildersintl.org
Admin: https://staging-admin.buildersintl.org
Environment Variables
Configured in deployment platform (Vercel, DO, etc.):
NODE_ENV=staging
API_URL=https://staging-api.buildersintl.org
DATABASE_URL=postgresql://staging-db.buildersintl.org:5432/myapp_staging
LOG_LEVEL=info
# External services (test/sandbox)
STRIPE_KEY=sk_test_...
SENDGRID_API_KEY=SG.staging...
# Feature flags
ENABLE_BETA_FEATURES=true
ENABLE_DEBUG_PANEL=true
# Monitoring
SENTRY_DSN=https://...@sentry.io/...
POSTHOG_API_KEY=phc_staging...
Database
Hosted database with sanitized data:
- Provider: Digital Ocean Managed PostgreSQL
- Backups: Daily automated backups
- Data: Sanitized copy of production (PII removed)
- Size: Smaller than production (representative sample)
Data Sanitization
Production data is sanitized before copying to staging:
-- Example sanitization script
UPDATE users
SET
email = CONCAT('user', id, '@example.com'),
phone = CONCAT('+1555000', LPAD(id::text, 4, '0')),
name = CONCAT('Test User ', id);
UPDATE orders
SET
shipping_address = 'Sanitized Address';
Access Control
- VPN: Not required (staging is publicly accessible)
- Authentication: Separate auth system (staging accounts)
- Admin Access: Limited to team members
Deployment Process
Automatic on merge to main:
- CI tests pass
- Build created
- Deploy to staging
- Smoke tests run
- Team notified in Slack
Testing on Staging
# Run E2E tests against staging
npm run test:e2e -- --baseUrl=https://staging-project.vercel.app
# Manual testing checklist
# - Authentication flows
# - Key user journeys
# - Payment processing (test mode)
# - Email notifications (test inbox)
# - Error handling
# - Performance (load times)
Monitoring
- Uptime Kuma: Monitors service availability
- Sentry: Tracks errors and exceptions
- PostHog: Analytics (separate staging project)
- Logs: Centralized logging system
Production Environment
Purpose
Live, user-facing services serving real users.
Characteristics
- Access: End users + limited team access
- Data: Real user data (PII, financial, etc.)
- Stability: Highly stable, manual deployment
- Deployment: Manual approval required
URL Structure
Web: https://buildersintl.org
API: https://api.buildersintl.org
Admin: https://admin.buildersintl.org
Environment Variables
Configured securely in deployment platform:
NODE_ENV=production
API_URL=https://api.buildersintl.org
DATABASE_URL=postgresql://prod-db.buildersintl.org:5432/myapp_production
LOG_LEVEL=warn
# External services (production)
STRIPE_KEY=sk_live_...
SENDGRID_API_KEY=SG.prod...
# Feature flags
ENABLE_BETA_FEATURES=false
ENABLE_DEBUG_PANEL=false
# Monitoring
SENTRY_DSN=https://...@sentry.io/...
POSTHOG_API_KEY=phc_prod...
# Security
RATE_LIMIT_ENABLED=true
CORS_ORIGINS=https://buildersintl.org
Database
Production-grade database:
- Provider: Digital Ocean Managed PostgreSQL
- Backups: Continuous + daily snapshots (30-day retention)
- High Availability: Primary + standby replicas
- Encryption: At rest and in transit
- Monitoring: Query performance, slow query log
Access Control
- VPN: Required for infrastructure access
- 2FA: Required for all admin access
- Principle of Least Privilege: Minimal access granted
- Audit Logging: All access logged and monitored
Deployment Process
Manual with approval gates:
- Create release tag
- Trigger release workflow
- Platform team approval required
- Deploy with health checks
- Smoke tests + monitoring
- Team notification
See Deployment Process for details.
Monitoring & Alerting
- Uptime Kuma: Service availability (1-minute checks)
- Sentry: Error tracking with alerting
- PostHog: User analytics and session recording
- CrowdSec: Security monitoring
- Custom Dashboards: Key business metrics
Alert Channels:
- Slack: #alerts channel
- PagerDuty: For critical incidents
- Email: For non-urgent notifications
Backup & Disaster Recovery
Database Backups:
- Point-in-time recovery available
- Daily full backups retained for 30 days
- Tested restore procedures quarterly
Application Backups:
- Code in Git (version controlled)
- Configuration in deployment platform
- Secrets in secure secrets management
Disaster Recovery Plan:
- RTO (Recovery Time Objective): 1 hour
- RPO (Recovery Point Objective): 5 minutes
- Documented runbooks for common scenarios
Secrets Management
Storage
GitHub Secrets: Used for CI/CD workflows:
Settings → Secrets and variables → Actions
Vercel Environment Variables:
Project Settings → Environment Variables
Digital Ocean:
- Secrets stored in
/opt/app/.env.productionon droplet - Access controlled via SSH keys
- Encrypted at rest
Rotation Policy
- API Keys: Rotate every 90 days
- Database Passwords: Rotate every 180 days
- SSH Keys: Rotate annually
- Service Account Tokens: Rotate every 90 days
Required Secrets per Environment
Development:
- Local database credentials
- Test API keys (Stripe, etc.)
- Development OAuth credentials
Staging:
- Staging database URL
- Test API keys
- Staging Sentry DSN
- Staging PostHog key
- Deployment credentials
Production:
- Production database URL
- Live API keys (Stripe, SendGrid, etc.)
- Production monitoring keys
- Domain certificates (auto-managed by Cloudflare)
- Deployment credentials
Environment-Specific Configuration
Feature Flags
Control features per environment:
// config/features.ts
const features = {
development: {
betaFeatures: true,
debugPanel: true,
analytics: false,
},
staging: {
betaFeatures: true,
debugPanel: true,
analytics: true,
},
production: {
betaFeatures: false,
debugPanel: false,
analytics: true,
},
}
export const isFeatureEnabled = (feature: keyof typeof features.development) => {
return features[process.env.NODE_ENV][feature]
}
Rate Limiting
const rateLimits = {
development: {
enabled: false,
requests: Infinity,
},
staging: {
enabled: true,
requests: 1000, // per hour
},
production: {
enabled: true,
requests: 100, // per hour
},
}
Logging
const logging = {
development: {
level: 'debug',
pretty: true,
},
staging: {
level: 'info',
pretty: false,
},
production: {
level: 'warn',
pretty: false,
},
}
Adding a New Environment Variable
-
Add to documentation
- Document purpose and format
- Specify which environments need it
-
Add to example files
# .env.example
NEW_VARIABLE=example_value -
Configure in deployment platforms
- Vercel: Project settings
- Digital Ocean: Update .env file on droplet
-
Update CI/CD workflows
- Add secret to GitHub if needed
- Update workflow files
-
Test in staging first
- Verify variable is accessible
- Ensure feature works correctly
-
Deploy to production
- Add variable to production environment
- Verify configuration
Troubleshooting
Environment Variable Not Loading
# Check environment
echo $NODE_ENV
# Verify .env file loaded
node -e "require('dotenv').config(); console.log(process.env)"
# Check deployment platform configuration
# Vercel: vercel env ls
# Digital Ocean: SSH and check .env file
Database Connection Issues
# Test database connectivity
psql $DATABASE_URL
# Check connection pool
# Monitor active connections
# Verify credentials are correct
Staging/Production Drift
If environments diverge:
- Document differences
- Create plan to reconcile
- Update infrastructure as code
- Apply changes consistently
Best Practices
- Environment Parity: Keep staging as close to production as possible
- Secrets Hygiene: Never commit secrets, rotate regularly
- Configuration as Code: Define environment config in version control
- Least Privilege: Grant minimum necessary access
- Monitor Everything: Track metrics and logs in all environments
- Test on Staging First: Always validate changes on staging before production
- Document Changes: Keep environment documentation up to date
- Automate Provisioning: Use infrastructure as code when possible
- Backup Regularly: Ensure all environments have backup strategies
- Review Access: Audit environment access quarterly
Resources
- Infrastructure Overview
- Deployment Process
- CI/CD Workflows
- Secrets Management (TODO: Detailed secrets guide)