# The values your app reads

> Learn how settings and secrets reach your app. See where each value lives, and how a build-time value differs from a run-time one.

Source: https://customhosted.com/configuration/

№ 01 Configuration

The settings, environment variables, and secrets your app reads at startup: what each one is, where it lives, and what a value baked into a static build actually gives away.

№ 02 Two things called config

## A setting, and a secret

Both arrive at your app the same way. What each one is, and who can read it back, are not the same question.

- A setting — A value that changes how your app behaves, and is not secret if someone sees it. — Example: A feature toggle, a display name, a region string, a log level. — Read back by: Anyone who can already read your code or your running app's output.
- A secret — A value that grants access, and must not leak — to a person, a log, or a public bundle. — Example: An API key, a database password, a signing key, a connection string. — Read back by: Named CustomHosted accounts only, to service or rotate it — see the matrix rows below.

№ 03 Where a value lives

## Where a value lives, hop by hop

Every value takes the same path, whether it is a setting or a secret.

1. 1 — You send the value — Through the quote channel, at onboarding or whenever it changes — never a spreadsheet or a chat message. — You
2. 2 — It is kept in an encrypted store — Sent once, at onboarding or whenever it changes, and kept in an encrypted store — never copied into a spreadsheet, a chat message, or a second system to keep in sync. — CustomHosted
3. 3 — It is injected at build time or deploy time — Which one depends on the hosting shape and the value itself — see the build-time-versus-run-time band below. — CustomHosted
4. 4 — It lands in the process environment at startup — The running app reads it at startup. It is never written into a file in your repository, so an agent reading the codebase sees the name of the variable your code uses, never the value stored in it. — The process
5. 5 — Your code reads it — The same way any app reads a setting or a secret — by name, from the environment it is running in. — You

№ 04 Build time against run time

## A build-time value is a public value

Said plainly, because nowhere else on this site has: a value baked into a static bundle ships to every visitor who opens it.

- A build-time value ends up inside the bundle — A static site or a single-page app has no server standing by at request time. Anything read into it at build time is baked into the files a browser downloads.
- That bundle is public — Every file shipped to a visitor's browser can be read by that visitor. A value baked in at build time is public the moment it ships — not hidden, only unlabelled.
- A run-time value stays on the server — A dedicated instance keeps a standing process. A value read from its environment at startup never leaves that process unless your own code sends it somewhere.
- The rule that follows — Never put a secret in a build-time value on a static site. A setting is fine there. A secret needs a standing process to hold it — see the shape table below.

№ 05 By hosting shape

## What holds a value, by hosting shape

Whether a change needs a rebuild or a restart depends on the shape, not the value.

| Shape | Holds | To change one |
| --- | --- | --- |
| Static Starter ST-STARTER | Build-time values only, baked into the deployed files. | A rebuild and redeploy — nothing to restart, because nothing stands running. |
| Static Pro ST-PRO | The same build-time values, once per environment — production and staging each hold their own. | A rebuild and redeploy of the environment you changed. |
| Dedicated M DD-M | Run-time values in the process environment, read fresh at every startup. | A restart of the process — see the restart-visibility table below for what you would notice. |
| Custom CU-0 | Whichever mix the design calls for — sized and confirmed at the quote stage. | Whatever the design calls for — confirmed once, not guessed at. |

What "restart" looks like on a running process, by shape:

- Static site — None — there is no running process to restart.
- Dedicated instance — A few seconds while the process restarts, confirmed by the health check above before the window closes.
- Managed database, minor version — A brief connection blip during failover — existing connections reconnect on their own.

№ 06 Changing one

## Changing a value

Sized inside the iteration allowance — around 120 minutes, the same 2-hour unit any small change draws from.

1. 1 — Send the new value — Through the quote channel, naming which variable and which environment. — You
2. 2 — It is stored, and rotated in — Stores the value you send and rotates it on request. — CustomHosted
3. 3 — It takes effect — A rebuild on a static shape, or a restart on a dedicated shape — see the restart-visibility table above. — CustomHosted
4. 4 — You are told it is done — A note confirming what changed, in the same shape as every other note on this site. — CustomHosted

To go back, send the previous value the same way — there is no separate undo button for a configuration change.

№ 07 Per environment

## Production values, staging values

Same infrastructure definition, different values — see [Environments](https://customhosted.com/environments) for the environment itself.

- Production — Its own set of values — the ones your live app actually reads.
- Staging — Its own separate set, not a copy of production's. Changing one never quietly changes the other.

№ 08 Rotation

## Rotating a value

Three real triggers, each with a place that owns it in full.

- A person leaves — Anything they held a key to on our side is revoked the same day — the same rule joiners and leavers already sets. See [Access — joiners and leavers](https://customhosted.com/access).
- A value leaks — Treated as a live incident: the value is rotated, and the exposure is worked the way any leaked credential is. See [Under attack — password guessing](https://customhosted.com/under-attack).
- A scheduled rotation — Send the replacement value whenever you choose — there is no console click, only the same quote channel as any other change. See [Access — secrets](https://customhosted.com/access).

№ 09 What it costs

## Nothing extra

A configuration change is priced the same as any other small change.

A config change sits inside the iteration allowance — 3 changes a month, 2 hours each, the same allowance covered under Agentic iteration — CodeHerder ($25/mo). See [The hours ledger](https://customhosted.com/hours) for the full ledger.

№ 10 The worked artifact

## This site's own configuration

Every row below is provable from this repository, not asserted.

- One build-time value, set on purpose — PUBLIC_CONTACT_ENDPOINT is read in at build time and ships inside this site's own static bundle — public by design, because it only names where the quote form posts to.
- No secret anywhere in the repository — This site holds no API key, password, or signing key of its own. The quote form itself carries no secret — it posts to a relay that holds the credential instead.
- A relay, not a direct write — The quote form sends a request to a relay rather than writing anywhere directly, so nothing this site's own code runs ever needs a stored credential.

№ 11 Said plainly

## The honest limits

Not buried in a footnote — the same discipline as every other honesty band on this site.

- No self-serve console — There is nowhere to click a value in or out yourself. Every change goes through the quote channel, the same as any other request on this site.
- A build-time value in a static bundle is public — Said plainly, not buried: baking a secret into a static build ships it to every visitor's browser. Use a run-time value on a standing process instead.
- We can read a value back — Named accounts only, to service or rotate a value. A named account, never a shared login.
- No per-branch configuration sets — Production and staging each hold their own values. There is no wider fleet of per-branch value sets on a standard plan.
- No feature-flag service — A setting can toggle behaviour, but there is no separate flag service here to turn one on or off per visitor. That is application code, not a platform feature.

№ 12 CodeHerder

## A name, never a value

This is the exact boundary CustomLabs draws for the CodeHerder agent — the one that makes agentic iteration safe to run against your live code.

It sees that your code reads a variable, never the value stored in it.

A briefed change that needs a new value comes back as a pull request naming the variable, not the value in it. A person sets the value once the change is reviewed — the same ship mechanics as any other briefed change:

1. 1 — A routine scan flags a dependency — The same kind of check that watches the infrastructure layers above, run against your application’s own dependency list. — CustomHosted
2. 2 — It's triaged as application-level, not infrastructure — A library your own code imports isn't ours to patch silently — it can change how the app behaves. — CustomHosted
3. 3 — Briefed as a change — Written up the same way any other change request is — this is what the Agentic iteration — CodeHerder add-on covers. — CustomLabs
4. 4 — An agent opens the pull request — The upgrade lands as a real pull request against the repository, with the test suite run against it. — CodeHerder
5. 5 — A human reviews and merges — Someone reads the diff before it goes anywhere near production — nothing here is auto-applied blind. — CustomLabs
6. 6 — It ships through the same pipeline — The same pipeline that deploys everything else on your stack ships this too — no separate process to babysit. — CustomHosted
7. 7 — You're told it's done — A note confirming what changed and that it merged, in the same shape as every other note on this site. — CustomHosted

№ 13 Answers

## Configuration questions

What people ask once "an environment variable" stops being self-explanatory.

1. 01 What counts as a secret, rather than just a setting? Anything that grants access on its own — an API key, a password, a signing key, a connection string. If seeing the value would let someone do something they should not, it is a secret.
2. 02 Can I read my own secret's value back? There is no console to read it from — ask, and we tell you.
3. 03 Is it safe to put an API key in a static site's build? No. A static build ships to every visitor's browser, so anything baked in at build time is public. Keep a secret on a dedicated shape that reads it at run time instead.
4. 04 Does changing a value take my app down? On a static site, a rebuild replaces the deploy — nothing was running to go down. On a dedicated instance, the process restarts — see the restart-visibility table above for exactly what that looks like.
5. 05 Do staging and production share the same values? No. Each environment holds its own set, so a value changed in one never quietly changes the other.
6. 06 Can the CodeHerder agent read or set a value? No, on both counts. It can see that your code reads a variable by name. It can open a pull request that adds a new one. It never sees or sets the value stored in it.
7. 07 What does a config change cost? Nothing on top. It sits inside the iteration allowance — 3 changes a month, 2 hours each, the same allowance any other small change draws from.

№ 14 Keep reading

## What configuration connects to

- [Logins An identity provider's client secret is exactly the secret this page defines — held the same way as any other.](https://customhosted.com/logins)
- [Access Who can read a secret's value back, and who can set one — the matrix rows this page quotes whole.](https://customhosted.com/access)
- [Repository The one real hazard inside the repository itself — a committed secret — and what happens when we find one.](https://customhosted.com/repository)
- [Environments The second environment itself — its address, who can reach it, and what data it holds.](https://customhosted.com/environments)
- [Patching The briefed-change mechanics this page's CodeHerder section reuses in full.](https://customhosted.com/patching)
- [Databases The connection string as a value — this page only names where it is read from.](https://customhosted.com/databases)
- [Email The relay credentials as a value — the same treatment as any other secret.](https://customhosted.com/email)
- [Under attack What a leaked value turns into, and the escalation this page's rotation section links to.](https://customhosted.com/under-attack)
- [The hours ledger The iteration allowance a config change is priced from — the same row this page's cost section quotes.](https://customhosted.com/hours)
- [The Loop The "config change" the loop ships, in the wider build-iterate-run picture this page is one step of.](https://customhosted.com/loop)
- [Deploys The build-time-versus-run-time trap above, from the other side — what a deploy actually does between a merge and a value being read.](https://customhosted.com/deploys)
- [Outside services Where the key this page stores actually gets used — the call it unlocks, and what happens when the far end changes or breaks.](https://customhosted.com/outside-services)
- [Forms The build-time-versus-run-time trap above, applied to a static page: no secret can live in a form's own markup.](https://customhosted.com/forms)

## Need a value changed, or a new one added?

Brief it through the same quote channel as any other request — see Access for who can read one back.

[Get a quote →](https://customhosted.com/contact)
