On this page
What environment configuration covers
Most applications run in at least three places: developers’ machines, a staging environment for testing and production for real users. Environment configuration is about keeping those places separate and consistent at the same time: separate so a test never touches real customer data, and consistent so something that works in staging also works in production.
It also covers how settings and secrets are managed. API keys, database passwords and third-party tokens should be stored securely, different per environment, and changeable without editing code.
Warning signs
- Staging and production share a database, or staging was pointed at production data “just for a test”.
- A test email or WhatsApp message once went to real customers.
- API keys are committed in the repository or shared in chat messages.
- Releases work in staging but fail in production because of a different runtime version or setting.
- Nobody is sure which settings differ between environments or why.
These problems rarely come from carelessness. They usually build up as a product grows quickly: a shortcut during a launch, a test that needed real data, a key shared to unblock a colleague. Sorting them out once, properly, stops them recurring.
What’s included
- An inventory of every setting and secret the application uses, per environment.
- Configuration moved into environment variables or configuration files outside the code.
- Secrets moved into a proper secret store and rotated where they had been exposed.
- Separate databases, storage buckets and third-party accounts or sandbox modes per environment.
- Staging aligned with production in runtime versions, services and configuration shape.
- Safe handling of outbound email, SMS and messaging in non-production environments.
- A documented list of what differs between environments and why.
For teams with contractors or agencies involved, we also set up access so each person sees only the environments and secrets they need, and access can be removed cleanly when an engagement ends.
How we approach it
- Audit the codebase, servers and CI settings for configuration and secrets.
- Design the target setup: where each value lives and who can read it.
- Move values out of code, create separate resources for each environment and rotate exposed secrets.
- Update the deployment process to inject configuration per environment.
- Test each environment end to end, including outbound messages, and document the result.
Changes to how configuration is loaded are made in development and staging first. Production is switched over last, during a planned window, with the previous configuration kept ready so the change can be reversed quickly if a value was missed.
Tools we use
Options range from well-protected environment files on the server to dedicated secret managers such as AWS Secrets Manager, Google Secret Manager, Azure Key Vault or HashiCorp Vault. CI platforms such as GitHub Actions and GitLab CI provide environment-scoped secrets and protection rules. Docker and Docker Compose make it easier to keep runtime versions identical across environments, and Terraform can create matching infrastructure for each one.
What should differ, and what should not
| Item | Same across environments? | Notes |
|---|---|---|
| Runtime and dependency versions | Yes | Differences here cause the classic “worked in staging” failures |
| Application code and build | Yes | The same build artefact should move through each stage |
| Database and storage | No | Each environment has its own; staging uses sanitised or synthetic data |
| Secrets and API keys | No | Separate keys, with sandbox or test modes for payment and messaging providers |
| Domains and URLs | No | Staging on its own subdomain, protected from search engines and the public |
| Resource sizes | Can differ | Staging can be smaller, as long as the architecture matches |
What affects timeline and cost
An application that already reads configuration from the environment is quick to organise. More time is needed where settings are scattered through code, many third-party services must be duplicated in sandbox mode, production data must be sanitised for staging, or secrets need rotating across several systems. Extra environments add some hosting usage, billed by your provider.
If a secret has been committed to a repository in the past, rotating it is essential even after it is removed from the code, because it remains in the history. We include that rotation in the plan rather than leaving it as a follow-up.
Common mistakes
- Copying production data into staging with real customer emails and phone numbers intact.
- Using live payment or messaging keys in staging.
- Parsing environment files by hand in a way that keeps quotes in values, producing confusing authentication failures.
- Leaving staging publicly reachable and indexed by search engines.
Related: Application Deployment, Security Auditing and Custom Software. See all DevOps & Deployment services, the DevOps guide, or contact us.
Frequently asked questions
Do we really need a staging environment?
For anything customers rely on, yes. It is where releases are checked safely before they reach real users and real data.
Can staging be smaller and cheaper than production?
Yes. It should match production’s architecture and versions, but it can use smaller servers.
Where should secrets be stored?
In a secret manager or the CI platform’s secret store, scoped to each environment. Never in the repository.
Can staging use real production data?
Only in sanitised form. Personal details should be removed or replaced so tests can never contact real customers.
We found an API key in our Git history. What now?
Rotate it immediately at the provider, then remove it from the code. Removing it alone is not enough because the history still contains it.
Talk to us about environment configuration
Clean separation of development, staging and production settings and secrets.