Cloud-native guide

Configuration and secrets in cloud-native applications

Most teams believe they have solved this because nothing is hardcoded and everything comes from an environment variable. That satisfies the letter of the rule and misses two of the three things that matter: whether a secret can be rotated without a redeploy, and whether it leaks into the places nobody thinks to check. Both problems surface at the worst possible time, which is during an incident involving a credential.

What belongs in configuration and what does not?

Anything that legitimately differs between environments, and nothing else. Database hostnames, API endpoints, bucket names, log levels, credentials. If a value is the same in staging and production, it is not configuration, it is a constant, and moving it out of the code buys nothing while making the behaviour harder to find.

Two categories get miscategorised routinely. Feature flags are not configuration: they change during the life of a running process, often several times a day, and they belong in something built for runtime toggling rather than in a variable that requires a restart to change. Business rules such as tax rates and thresholds are not configuration either, because they need history, an audit trail and usually a user interface, which makes them data.

The test that resolves most arguments is to ask who changes the value and how often. Set once per environment by an engineer means configuration. Changed during business hours by someone who is not an engineer means data with a screen attached, and putting it in an environment variable guarantees a deploy every time the business wants a different number.

Environment variables or mounted files?

Environment variables for non-sensitive configuration, mounted files for secrets. The distinction is not stylistic: environment variables are inherited by every child process, visible to anything that can read the process table, and captured by a surprising number of crash reporters and error trackers by default. A mounted file is readable only by processes that open that path.

The second difference is rotation. An environment variable is fixed for the life of the process, so changing it requires a restart of every instance. A mounted secret is updated in place by the platform, which means an application that re-reads the file can pick up a new credential without a deploy.

MechanismSuited toLeaks throughRotation
Environment variablesHostnames, feature toggles, log levels, non-sensitive settingsChild processes, crash dumps, error trackers, debug endpointsRequires a restart of every instance
Mounted secret filesDatabase passwords, API keys, certificatesAnything that can read the container filesystemUpdated in place; the app must re-read
Secret manager, read at runtimeShort-lived credentials and dynamic leasesApplication logs, if the response is loggedNative, including automatic expiry
Config maps or plain config objectsNon-sensitive structured settingsAnyone with read access to the namespaceUpdated in place, same re-read requirement
Baked into the imageNothingEvery image layer, forever, including the registryRebuild and redeploy
CI/CD pipeline variablesDeploy-time credentials onlyBuild logs, and any fork or pull request buildManual, and easily forgotten

Why do secrets leak from environment variables?

Through five specific routes, none of which involve anybody doing anything obviously wrong. On Linux, the environment of a process is readable from the proc filesystem by anything running with sufficient privilege in the same container. Child processes inherit the whole environment, so a shell-out to a command line tool passes every credential along with it. Crash handlers and error tracking libraries commonly attach environment state to reports, sending credentials to a third party. Many frameworks expose a debug or diagnostics page listing the environment. And startup logging that prints configuration for troubleshooting is the direct route into your log aggregator, where it is now retained and searchable.

The consequence of each is the same and worth naming: the credential is now in a system with different access controls and a different retention period from the secret store it came from. Revoking it later does not remove it from six months of log archives.

Mitigations are straightforward once you know the routes. Scrub known secret keys in the error tracker configuration rather than trusting the defaults, never log the whole configuration object, disable framework diagnostics pages in production, and prefer file-based delivery for anything that would matter if it appeared in a log line.

What does rotation actually require of the application?

That it can acquire a new credential without being restarted, and that its existing connections do something sensible when the old one stops working. The second part is what gets missed. A connection pool authenticates when a connection opens, so pooled connections keep working with a revoked password until they are recycled, which makes the rotation appear successful and produces failures hours later when the pool refreshes.

The workable pattern is to read credentials through an accessor rather than capturing them at startup, so that every new connection uses the current value. Then set a maximum connection lifetime in the pool so old connections retire on a known schedule rather than living indefinitely. Rotation then completes within that lifetime without a deploy and without an outage.

The version to avoid is rotation by rolling restart. It works, it is what most teams do, and it means every credential change is a deployment event that has to be scheduled, which is precisely why credentials end up not being rotated. If the only way to change a password is to redeploy production, the password will not be changed.

How should local development get its configuration?

From a checked-in example file listing every required variable with placeholder values, plus a local file that is ignored by version control. The example file is the part that gets skipped and the part that matters, because it is the only machine-readable record of what the application actually needs, and it turns onboarding from a conversation into a command.

Give developers credentials that only work locally. The pattern where a new engineer is handed production read credentials for convenience is how those credentials end up on unencrypted laptops and in support chats, and it is entirely avoidable when the local environment starts real backing services in containers with throwaway passwords.

Make the application fail loudly when a required value is absent. Configuration that silently falls back to a default is the mechanism behind a specific class of incident: a variable is renamed, the deploy succeeds, the application starts, and it quietly connects to the wrong place or runs with authentication disabled. Validate the full set at startup and refuse to start if anything required is missing.

What can you check this afternoon?

Four things. Run the image history for your production container and look at the build layers for anything resembling a credential, since a secret passed as a build argument or copied and later deleted still exists in an earlier layer. Grep your log aggregator for the name of a known configuration key and see what comes back. Check your error tracker for a captured environment on any recent exception. And take a non-production database password, rotate it in the secret store, and time how long until the application uses the new one without help.

The fourth is the informative one. If the answer is that it never does until someone redeploys, you have discovered that your rotation procedure is a deployment procedure, which tells you what will happen the day a credential has to be replaced urgently.

None of these need a project to run. They need an afternoon and someone with access to the pipeline, and each has a binary answer that either closes the question or defines the next piece of work.

Common questions

Should secrets be stored in environment variables?
Preferably not. Environment variables are inherited by child processes, readable from the process table, commonly captured by error trackers and crash handlers, and often exposed on framework diagnostics pages. They also cannot be changed without restarting the process. Mounted secret files or a secret manager read at runtime avoid both problems, and allow rotation without a deploy.
What counts as configuration and what does not?
Configuration is anything that legitimately differs between environments: hostnames, endpoints, bucket names, log levels, credentials. A value identical in staging and production is a constant, not configuration. Feature flags belong in a runtime toggling system because they change during the life of a process, and business rules such as rates and thresholds are data, because they need history and an audit trail.
How do you rotate a database password without downtime?
Read the credential through an accessor rather than capturing it at startup, so every new connection uses the current value, and set a maximum connection lifetime in the pool so existing connections retire on a known schedule. Rotation then completes within that lifetime. Without this, pooled connections keep working with a revoked password and fail hours later when the pool refreshes.
Why should an application fail to start when configuration is missing?
Because a silent fallback to a default causes a specific class of incident: a variable is renamed, the deploy succeeds, the process starts, and it quietly connects to the wrong system or runs with authentication disabled. Validating the complete required set at startup and refusing to start turns a subtle production problem into an obvious deployment failure.
Can secrets hide inside a container image?
Yes. A secret passed as a build argument, or copied in and deleted in a later step, still exists in the earlier layer and travels with the image into the registry. Inspecting the build history of a production image will show it. This is why secrets should be delivered at runtime rather than at build time, and why registry access should be treated as sensitive.

More on Cloud-native development

Let’s create something out of this world together.

Have a project in mind? Contact us for expert design and development solutions. Let’s discuss how we can help grow your business.

Azaadi Offer

Claim a free security assessment

Until 31 August we're covering the cost of a full vulnerability assessment and penetration test. Mention it in your message and we'll scope it with you.

  • Web application testing, authenticated and unauthenticated
  • Mobile application testing across iOS and Android
  • External network and infrastructure assessment
  • Manual exploitation by engineers, not scanner output

Testing and the report are free. Fixing what we find is quoted separately, with no obligation to accept.

Read the full offer

Tell us what you are trying to build and we will tell you plainly whether we are the right people for it. Book a call with an expert to work through the detail, or ask for a fixed quote if the scope is already clear. No obligation either way.

Four fields is all we need to get started.

Fastnexa Logo

© 2026 fastnexa. All rights reserved.