Docs
Guidesince cloud@2026-09-10

Serverless functions

A function is your code from the first line, so values arrive through the platform's own store, and a sync writes them on Lambda, Cloud Run, Workers, Vercel and Deno Deploy.

A function is your code from the first line. Nothing of yours runs before it, so there is no process for penv run to wrap and no build step guaranteed to have written a file. penv ships no library for reading a value at boot either, because a network call on every cold start is the runtime read penv avoids.

Values reach a function through the platform's own store, and the console writes them there for you.

What a sync writes

PlatformWhat it writesWhen the value goes live
AWS LambdaThe function's environment variables on $LATESTOn the next instance the platform provisions
Google Cloud RunThe container's environment in a new revisionWhen that revision takes traffic
Cloudflare WorkersThe Worker's secret bindingsImmediately, because the write rolls a new script version
VercelThe project's environment variablesOn the next deploy
Deno DeployOne app's variables, for the context you pickOn the next deploy
Deno Deploy layersOne layer's variables, read by every app that includes itOn the next deploy

Vercel has a second path as well, because a Vercel build can run a command. See deploy to Vercel.

Connect the platform

Open Integrations in the console, pick the platform, and give it what it needs to write.

PlatformWhat it authenticates withWhat one connection covers
AWS LambdaA role you grant penv, with an external id penv generatesOne account, and function names under one prefix
Google Cloud RunA service account key fileOne project and one region
Cloudflare WorkersAn API token with Workers Scripts EditOne account
VercelAn access token, plus a team id on a team accountThe token's own scope
Deno DeployAn access token from console.deno.comThe app named on the connection
Deno Deploy layersAn access token that can edit layersWhichever layer a sync names

Then map one penv environment onto one target: a Lambda function name, a Cloud Run service name, a Worker name, a Vercel project and deployment target, or a Deno Deploy context.

Run a dry run before you apply. It names the keys a real run would write and the keys it would delete, using names alone, so you see a prune before it happens rather than after.

What each platform makes you live with

AWS Lambda replaces the whole environment variable map on every write, so penv reads the current configuration and writes the merged map back, pinned to the revision it read. A published version's configuration is locked, so writes target $LATEST alone. The write is asynchronous, which is why the value arrives on the next instance rather than the next request.

Importing from Lambda needs kms:Decrypt. A variable encrypted under a customer managed key cannot be read at all, and penv reports that rather than treating it as empty.

Google Cloud Run works the same way with a revision in place of a version. penv reads the service and writes the merged list back pinned to the etag that read returned, treating both 409 and 412 as a lost race and re-reading afterward. A variable that points at Secret Manager is listed and preserved byte for byte, and never fetched, so a sync does not quietly flatten one into a literal.

Cloudflare Workers is export only, and not by choice. Cloudflare returns secret names and never their values, so there is nothing for an import to read.

Deno Deploy is export only for the same reason: every variable penv writes there is marked secret, and Deno omits the value of a secret variable from its response. Deno does not say whether a change reaches an isolate that is already running, so penv reports the write as live on the next deploy.

Where the record stops

Once a value sits in the platform's store, the platform serves it. Reads there are not penv reads, so they land no entry in your audit log.

You get an entry forYou do not get an entry for
The sync that wrote the value, and what it changedYour function reading the variable it was given
A reveal, a write and a delete in penvA person reading the value in the platform's own console

That is the trade for a boot with no network call in it. Where you need every read written down, run the code somewhere you can wrap with penv run.

Dynamic values are skipped

A dynamic value has no stored value to copy, because it is minted on request. A sync skips it and names it in the run report. See dynamic values.

Deno Deploy proves who it is

Deno Deploy sits in both catalogs. The sync above writes into its variables, and a deployment can also mint its own token and authenticate as itself, which is the only function platform where that is true.

PartValue
Issuerhttps://oidc.deno.com
Subjectdeployment:<organization>/<app>/<context>
AudienceYour workspace id
import { getIdToken } from "jsr:@deno/oidc";

const T = await getIdToken("<ORG_ID>");
const r = await fetch("https://penv.cloud/api/v1/auth/oidc", {
  method: "POST",
  headers: { "content-type": "application/json" },
  body: JSON.stringify({ token: T }),
});
Deno.env.set("PENV_TOKEN", (await r.json()).credential);

The issuer is shared by every Deno customer, so the organization slug in the subject is what scopes the trust to you.

Do it in order

  1. Open Integrations in the console and connect the platform.
  2. Give it the credential it asks for, and let the connection verify before you go on.
  3. Map one penv environment onto one function, service, Worker or Deno Deploy context.
  4. Choose the write policy. Prune deletes keys your penv environment does not have.
  5. Run a dry run and read the plan.
  6. Apply, then redeploy or restart so the platform picks the values up.

External Secrets Operator