Skip to content

Values And Versioning

Secret values are read through the Secret product object. The product supports plain current values and versioned values stored inside one Cloudflare secret.

Use secret.static() when the operator supplies the value:

Terminal window
const stripeSecret = secret.static({
name: "stripe-secret",
namespace: "billing",
})
app.use(stripeSecret)

Read the current value:

Terminal window
const apiKey = await stripeSecret.current().text()

You can parse structured values when the secret contains JSON:

Terminal window
const credentials = await stripeSecret.current().json<{
clientId: string
clientSecret: string
}>()

Use secret.random() for generated keys:

Terminal window
const sessionKey = secret.random({
name: "session-key",
namespace: "auth",
bytes: 32,
})
app.use(sessionKey)

bytes defaults to 32. It must be an integer from 16 to 1024.

Use secret.generated() when a product-owned apply flow owns value generation outside application code:

Terminal window
const apiSigningKey = secret.generated({
name: "api-signing-key",
namespace: "auth",
bytes: 32,
})
app.use(apiSigningKey)

secret.generated() stores generated-value intent in the app spec and resource graph. Direct Cloudflare deploys bind an already configured Secrets Store value. Product-specific provider apply steps can write generated values when they own the generation flow, such as Storage R2 API token credentials. Scheduled rotation runs through layer secret rotate.

Use versioned values when old data, signatures, cookies, or tokens may still need old keys.

Terminal window
const encryptionKey = secret.random({
name: "encryption-key",
namespace: "storage",
rotation: {
everyDays: 90,
retain: {
mode: "retain_forever",
},
},
})
app.use(encryptionKey)

Read the latest value:

Terminal window
const currentKey = await encryptionKey.current().bytes()

Read a specific version:

Terminal window
const oldKey = await encryptionKey.version("v2").bytes()

Read the value active at a known time:

Terminal window
const key = await encryptionKey.at(record.encryptedAt).bytes()

Read all values active at a time. This is useful during signing-key overlap windows:

Terminal window
const activeKeys = await sessionKey.active({
at: "2026-05-25T00:00:00.000Z",
})
for (const key of activeKeys) {
const value = await key.text()
}

Plain values are treated as the current version:

Terminal window
sk_test_xxx

JSON version format:

Terminal window
{
"current": "v3",
"versions": {
"v2": {
"value": "old-secret-value",
"activeFrom": "2026-05-01T00:00:00.000Z",
"expiresAt": "2026-06-01T00:00:00.000Z"
},
"v3": {
"value": "new-secret-value",
"activeFrom": "2026-05-25T00:00:00.000Z"
}
}
}

Compact key-value format:

Terminal window
current=v3;v2=old-secret-value;v2_expires=2026-06-01T00:00:00.000Z;v3=new-secret-value

The runtime chooses the current version in this order:

  1. The version marked by current.
  2. The last version in the parsed value.
  3. The plain text value.

Every Secret has a product address:

Terminal window
$SECRET.<namespace>.<name>

For namespace: "auth" and name: "session-key", the default address is:

Terminal window
$SECRET.auth.session-key

The runtime binding name is generated from the same declaration:

Terminal window
LAYERON_SECRET_AUTH_SESSION_KEY