24.12. Production Environments
Table of Contents
Understanding Production Environments
A production environment is where real users interact with your application and real data is stored. Everything you do in CI/CD ultimately targets this environment, so you must treat it very differently from development and testing.
This chapter focuses on what is unique about production environments in a CI/CD context: how they are structured, protected, and updated safely.
What Makes Production Different
In many teams you will see at least three main environments:
| Environment | Typical Users | Purpose |
|---|---|---|
| Local | Individual developers | Daily coding, experiments |
| Staging | QA, developers, product | Final testing before release |
| Production | Real customers | Live system that must stay reliable |
Production has special constraints:
- High availability: Downtime is expensive.
- Data integrity: Data is often irreplaceable.
- Security: It holds real user data and secrets.
- Predictability: Changes must be controlled and auditable.
In production, stability and safety are more important than speed of change.
Never treat production as a place to “try things and see what happens”.
Typical Production Environment Setup
A basic production environment often includes:
- One or more application servers running your backend.
- A database server such as PostgreSQL.
- A cache such as Redis.
- A reverse proxy or load balancer such as Nginx or a cloud load balancer.
- Object storage for files, for example S3.
- Monitoring and logging stack such as Prometheus, Grafana, and an error tracker.
For small systems, some of these can be combined on a single virtual machine, but the logical separation still exists. In CI/CD, you treat them as separate components, each with their own configuration and deployment flows.
Separation of Concerns in Production
In production you separate concerns more strictly than in development:
- Code vs configuration
- Code is built and versioned in Git.
- Configuration is injected at runtime with environment variables, config files, or secret managers.
- Application vs data
- You can redeploy application containers frequently.
- Databases and file storage must be changed carefully and usually independently.
- Stateless vs stateful components
- Stateless components (web/API containers) can be scaled and replaced often.
- Stateful components (databases, queues, storage) are persistent and have stricter change rules.
CI/CD pipelines must respect these differences. For example, rolling out a new application image is cheap, but applying a database migration is not.
Protecting Production in CI/CD
You rarely want every push to automatically update production. Instead, you add safeguards.
Common protection mechanisms:
- Protected branches
- Only certain branches, for example
mainorrelease/*, can trigger production deployments. - Only authorized users can merge to these branches.
- Manual approvals
- Pipelines for production include a manual “approval” step.
- Ops or senior engineers confirm that the release is ready.
- Restricted runners or agents
- Only specific CI runners, with limited credentials, are allowed to deploy to production.
- Even if someone misconfigures a job, it cannot push to production without the right runner.
- Least privilege credentials
- CI uses a special service account with exactly the permissions it needs.
- For example, it can deploy containers and run migrations, but not drop databases.
Production deployment jobs should never use your personal admin credentials.
Always use scoped, revocable service accounts with minimum required permissions.
Release Strategies for Production
CI/CD to production is not just “build and deploy”. The way you release changes affects user experience and risk.
1. Direct deployment
The simplest form:
- Build image.
- Stop old application.
- Start new application.
This is acceptable for small internal systems, but it causes downtime.
2. Blue / Green deployments
You maintain two environments:
- Blue: currently live version.
- Green: new version.
Process:
- Deploy new version to Green.
- Run tests and smoke checks on Green.
- Switch traffic from Blue to Green, for example by changing load balancer config.
- Keep Blue around for quick rollback, then remove it when confident.
Advantages:
- Very fast rollback: just switch traffic back.
- Allows testing the new version in a production-like environment before users see it.
3. Rolling deployments
You update a subset of instances at a time:
- Have $N$ application instances behind a load balancer.
- Take 1 instance out of rotation.
- Update that instance to the new version.
- Put it back in rotation.
- Repeat until all $N$ are updated.
Rolling deployments minimize downtime and can be partly automated by your orchestrator (for example Kubernetes).
4. Canary releases
You send a small percentage of traffic to the new version first:
- Deploy the new version alongside the old.
- Route, for example, 5% of traffic to the new version.
- Monitor metrics and errors.
- If everything is fine, gradually increase to 100%.
- If not, route back to the old version.
Canary releases are very useful when releasing risky changes in production.
Environment Configuration in Production
Configuration management in production has stricter rules than in development.
- Environment variables for non‑secret config, for example
APP_ENV=production,LOG_LEVEL=INFO. - Secret managers or secure vaults for sensitive values, for example API keys and database passwords.
- Immutable images: containers are built once, and the same image is used in staging and production. Only configuration differs.
Typical pattern:
- CI builds a Docker image from a specific Git commit.
- CI pushes this image to a registry with a version tag, for example
my-api:1.4.0. - CI deploys the image to staging.
- After tests and approvals, CI deploys the same image to production, but with different environment variables.
Never embed production secrets in:
- Source code
- Docker images
- Public CI logs
Use environment variables, secret managers, or encrypted configuration files managed outside the code repository.
Handling Database Changes in Production
Databases in production are sensitive. Schema changes must be coordinated with application releases.
Typical approach in CI/CD:
- Migration step in the pipeline
- Before or during deployment, a job runs migration scripts.
- For example, using Alembic for SQLAlchemy.
- Backward‑compatible migrations
- First migration: add new columns or tables.
- Second migration: update application to use new columns.
- Later migration: remove old columns when no longer used.
- Safe failure behavior
- If migration fails, the deployment should stop.
- Application should not start with a partially updated schema.
Example sequence:
- Version 1 uses
users.name. - You want to split into
users.first_nameandusers.last_name.
You design releases like this:
- Release A (migration only)
- Add
first_nameandlast_namecolumns, keepname. - Optionally backfill from
name. - Release B (application update)
- Application writes to and reads from
first_nameandlast_name. - Still writes
namefor safety. - Release C (cleanup)
- Remove
namecolumn, after verifying nothing uses it.
This multi‑step plan avoids production outages caused by incompatible schema changes.
Versioning in Production
Every production deployment should be traceable:
- Version tags: Tag Git commits and container images, for example
v1.3.2. - Release notes: Document what changed in this version.
- Build metadata: CI can embed build info into the application, for example a
/healthor/versionendpoint that returns:
{
"version": "1.3.2",
"git_commit": "abc1234",
"build_time": "2026-08-27T10:15:00Z"
}This helps you answer:
- Which version is running in production?
- Which commit introduced this bug?
- What changes are currently live?
Observability Requirements in Production
Production environments must be observable. CI/CD deployments should be coupled with checks of:
- Metrics: error rate, latency, throughput, CPU, memory, etc.
- Logs: structured logs, request logs, error logs.
- Health checks: endpoints that confirm the application and dependencies are working.
In practice:
- After deployment, CI triggers basic smoke tests.
- Team members check dashboards for spikes in:
- HTTP 5xx errors.
- Response times.
- Database query time.
- If metrics degrade beyond a threshold, you consider rollback.
You can even automate this:
- Some systems support automated rollback if health checks fail or error rate increases after a deployment.
Rollback Strategies
No matter how careful you are, some releases will fail in production. Plan rollbacks ahead of time.
Common rollback options:
- Roll back to previous container image
- Keep at least one previous release available.
- CI/CD can redeploy the earlier version quickly.
- Blue / Green rollback
- If you use Blue / Green, you just switch traffic back to the previous environment.
- Feature flag kill switch
- If a particular feature causes problems, you disable it via configuration without a full rollback.
Key guidelines:
- Practice rollbacks in staging so the team knows the exact steps.
- Keep rollback fast and documented.
- Roll back first, then investigate, not the other way around.
In production incidents, time matters.
Have a predefined rollback plan instead of inventing it during an outage.
Access Control and Auditing
In production, you control who can:
- Trigger deployments.
- Change configuration.
- Access logs and metrics.
- Read or modify data directly.
Core practices:
- Role‑based access control in your CI/CD platform.
- Approval flows for production changes.
- Audit logs of:
- Who deployed what.
- When it was deployed.
- Which version was deployed.
This is important for both security and debugging.
Example: Simple Production Pipeline Flow
A minimal, safe flow for production might look like this:
- Developer merges feature branch to
main. - CI builds Docker image
my-api:1.0.0and runs tests. - CI deploys
my-api:1.0.0to staging automatically. - Staging tests pass, QA verifies features manually.
- A release manager clicks “Promote to production” in CI.
- CI:
- Applies database migrations in production.
- Performs a rolling deployment of
my-api:1.0.0to application servers. - Runs smoke tests against production.
- Monitoring shows stable metrics for 30 minutes.
- Release is marked successful in the release log.
If something goes wrong at step 6 or 7:
- The pipeline has a “Rollback to 0.9.3” job.
- Release manager triggers rollback.
- Systems go back to the previous version, and the team investigates offline.
Summary
Production environments are special because:
- They serve real users and hold real data.
- They demand higher standards for security, safety, and observability.
- CI/CD must include protections, rollouts, and rollbacks tailored to this environment.
When you design CI/CD for production, always optimize for predictability, safety, and traceability, even if that seems slower. In real systems, controlled change is far more valuable than fast, chaotic change.
Views: 8
KAHIBARO