Environment Separation Guide
Overview
This backend implements strict environment separation to ensure development, testing, and production environments are fully isolated, secure, and reproducible.
Why Strict Environment Separation Matters
Safety
- Prevents production data contamination during testing
- Ensures test databases never touch production data
- Makes configuration bugs visible immediately
Reproducibility
- Each environment has explicit, validated configuration
- No silent fallbacks or hidden defaults
- Configuration is version-controlled via example files
Security
- Production enforces DEBUG=false (fail-fast if violated)
- Secrets are environment-specific
- Test environments use mock API keys
Speed
- Development uses optimized settings for fast feedback
- Testing uses isolated resources for parallel execution
- Production uses optimized settings for performance
Architecture
Three Environments
| Environment | Purpose | Database | Debug | Logging | Typical Use |
|---|---|---|---|---|---|
| development | Local development | Dev DB | true | DEBUG | Hot reload, API docs, verbose errors |
| testing | Automated tests | Test DB | true | INFO | pytest, CI/CD, isolated tests |
| production | Live deployment | Prod DB | false | WARNING | Production API, strict security |
Configuration Files
.env.development.example → Copy to .env.development
.env.testing.example → Copy to .env.testing
.env.production.example → Copy to .env.production
.env → Fallback (not recommended for production)
Environment Loading
- Application reads
ENVvariable - Validates
ENVagainst allowed values (development, testing, production) - Loads
.env.{ENV}file (e.g.,.env.testing) - Falls back to
.envif environment-specific file doesn't exist - Validates all constraints (DATABASE_URL required, production DEBUG=false, etc.)
- Fails fast if any constraint is violated
Setup Instructions
1. Development Environment
# Copy example file
cp .env.development.example .env.development
# Edit with your settings
nano .env.development
# Key settings to change:
# - DATABASE_URL: Use a DEVELOPMENT database
# - DEBUG: Keep as true
# - LOG_LEVEL: DEBUG for maximum visibility
# - DB_ECHO: true to see SQL queries
Run development server:
cd backend
export ENV=development # Linux/Mac
# OR
set ENV=development # Windows CMD
# OR
$env:ENV="development" # Windows PowerShell
uvicorn src.main:app --reload --host 0.0.0.0 --port 8000
2. Testing Environment
# Copy example file
cp .env.testing.example .env.testing
# Edit with your settings
nano .env.testing
# Key settings to change:
# - DATABASE_URL: Use a separate TEST database
# - DEBUG: Keep as true
# - LOG_LEVEL: INFO (less noise than DEBUG)
# - DB_ECHO: false (unless debugging tests)
Create test database:
# PostgreSQL
createdb physical_ai_handbook_test
psql -c "GRANT ALL PRIVILEGES ON DATABASE physical_ai_handbook_test TO test;"
# Or use in-memory SQLite (faster, but limited features)
# DATABASE_URL=sqlite+aiosqlite:///:memory:
Run tests:
cd backend
export ENV=testing
pytest # All tests
pytest -m unit # Only unit tests
pytest -m integration # Only integration tests
pytest -v # Verbose output
pytest --cov # With coverage
3. Production Environment
# Copy example file
cp .env.production.example .env.production
# Edit with your PRODUCTION settings
nano .env.production
# CRITICAL settings:
# - ENV: Must be "production"
# - DEBUG: MUST be false (enforced)
# - DATABASE_URL: Production database with strong password
# - LOG_LEVEL: WARNING or ERROR (reduce log volume)
# - All API keys: Use production keys
Run production server:
cd backend
export ENV=production
# Do NOT use --reload in production
# Use production WSGI server
gunicorn src.main:app \
--workers 4 \
--worker-class uvicorn.workers.UvicornWorker \
--bind 0.0.0.0:8000 \
--access-logfile - \
--error-logfile -
Configuration Reference
Core Settings
| Variable | Required | Development | Testing | Production |
|---|---|---|---|---|
ENV | Yes | development | testing | production |
DEBUG | Yes | true | true | false (enforced) |
LOG_LEVEL | No | DEBUG | INFO | WARNING |
DATABASE_URL | Yes | Dev DB | Test DB | Prod DB |
DB_ECHO | No | true | false | false |
Validation Rules
-
ENV must be valid
- Only:
development,testing,production - Invalid values cause immediate failure
- Only:
-
DATABASE_URL is required
- Cannot be empty
- Application fails to start without it
-
Production MUST have DEBUG=false
- Running production with DEBUG=true is a security risk
- Application fails to start if violated
-
Per-environment isolation
- Test database must not be production database
- Development database must not be production database
- Each environment loads its own configuration
Best Practices
Development
- ✅ Use separate database from production
- ✅ Enable DB_ECHO to see SQL queries
- ✅ Use LOG_LEVEL=DEBUG for troubleshooting
- ✅ Keep API keys separate from production
- ❌ Never commit .env.development with real secrets
Testing
- ✅ Use completely isolated test database
- ✅ Use mock API keys (not real ones)
- ✅ Set ENV=testing before running tests
- ✅ Clean up test data after tests
- ❌ Never point tests at production database
Production
- ✅ DEBUG must be false (enforced)
- ✅ Use strong, randomly generated passwords (32+ chars)
- ✅ Store secrets in secret manager (AWS Secrets Manager, etc.)
- ✅ Enable SSL/TLS for database connections
- ✅ Use LOG_LEVEL=WARNING or ERROR
- ✅ Rotate secrets regularly (every 90 days)
- ❌ Never commit .env.production to version control
- ❌ Never run production with --reload flag
Security Checklist
Before Deploying to Production
-
DEBUG=false(verified) - Strong database password set
- Production API keys configured
- Database backups enabled
- Monitoring and alerts configured
- SSL/TLS certificates installed
- Security headers configured
- Rate limiting enabled
- CORS properly configured
- Secrets stored in secret manager
- Log aggregation configured
- Error tracking enabled (Sentry, etc.)
- Firewall rules configured
- Regular security audits scheduled