Runtime Secrets vs Build-Time: Which Approach Is Right?
Two fundamentally different approaches to secrets management. Here's how to choose.
When it comes to getting secrets into your application, you have two basic choices:
- Build-time: Inject secrets during deployment. They become part of the built artifact.
- Runtime: Fetch secrets when the application needs them. Nothing is baked in.
Both approaches work. Both have tradeoffs. Here's a practical comparison to help you decide.
Build-time secrets: The traditional approach
This is what most developers do by default. You set environment variables in your deployment platform (Vercel, Railway, Heroku). During the build process, these variables are injected into your application.
# Vercel dashboard
STRIPE_KEY=sk_live_xxx
DATABASE_URL=postgres://xxx
# Your code
const stripe = new Stripe(process.env.STRIPE_KEY);
// STRIPE_KEY was replaced with actual value at build timePros of build-time
- Simple: No extra infrastructure. Just set variables and deploy.
- Fast: No network call to fetch secrets. They're already in memory.
- Works offline: Once deployed, no external dependency.
Cons of build-time
- Rotation requires redeployment: Change a secret? Rebuild and redeploy everything.
- No audit trail: Who changed what, when? You don't know.
- Duplication: Same secret copied to multiple platforms.
- Secrets in build logs: Depending on your CI/CD, secrets might appear in logs.
Runtime secrets: The modern approach
With runtime fetching, your application retrieves secrets when it needs them. The only thing baked into your deployment is a token that grants access to the secrets manager.
# Vercel dashboard
KEVORAX_TOKEN=kev_proj_xxx # Only the access token
# Your code
async function getStripe() {
const res = await fetch(
'https://app.kevorax.com/api/runtime/secrets/STRIPE_KEY',
{ headers: { 'Authorization': `Bearer ${process.env.KEVORAX_TOKEN}` } }
);
const { value } = (await res.json()).data;
return new Stripe(value);
}
// Actual secret fetched fresh every timePros of runtime
- Instant rotation: Update a secret once, all deployments see it immediately.
- Full audit trail: Every access logged with timestamp and source.
- Single source of truth: One place to manage all secrets.
- Secrets never in builds: Only tokens in your deployment, not actual secrets.
Cons of runtime
- Network dependency: Your app needs to reach the secrets manager.
- Latency: Each fetch adds a network round-trip (mitigated by caching).
- Additional cost: Secrets managers aren't free (though Kevorax is $5/month).
When to use each approach
Use build-time if:
- You have a single deployment target
- Secrets rarely change
- You're okay with redeploying to rotate
- You don't need audit logs
Use runtime if:
- You deploy to multiple platforms
- You rotate secrets regularly (or should)
- You need to know who accessed what
- You want to change secrets without redeploying
- You're using AI coding tools and want to keep secrets out of prompts
The hybrid approach
In practice, many teams use a hybrid approach:
- Build-time for non-sensitive configuration (feature flags, API endpoints)
- Runtime for sensitive secrets (API keys, database credentials)
This gives you the simplicity of environment variables for config that doesn't need protection, while keeping actual secrets secure and rotatable.
Handling the latency concern
The most common objection to runtime secrets is latency. Every API call to fetch a secret adds ~50-100ms. For a cold start, that adds up.
The solution is caching:
// Cache secrets with a 5-minute TTL
const secretsCache = new Map();
const CACHE_TTL = 5 * 60 * 1000; // 5 minutes
async function getSecret(name) {
const cached = secretsCache.get(name);
if (cached && Date.now() - cached.timestamp < CACHE_TTL) {
return cached.value;
}
const res = await fetch(`https://app.kevorax.com/api/runtime/secrets/${name}`, {
headers: { 'Authorization': `Bearer ${process.env.KEVORAX_TOKEN}` }
});
const { value } = (await res.json()).data;
secretsCache.set(name, { value, timestamp: Date.now() });
return value;
}With caching, you get the benefits of runtime fetching with near-zero latency after the first request. Even rotation still works — just set a reasonable TTL (5-15 minutes is common).
The verdict
For solo developers and small teams in 2026, runtime secrets are almost always the right choice. The benefits — instant rotation, audit logging, single source of truth — far outweigh the minimal complexity.
Build-time secrets made sense when deployment was manual and infrequent. Modern CI/CD makes deployment easy, but it doesn't make secret rotation easy. Runtime fetching solves that.
Ready to try runtime secrets?
Kevorax makes runtime secret fetching simple. One vault, one API, instant rotation. $5/month flat.
Start Free Trial