Environment Variables and Secrets in Amplify Gen 2
Separate public configuration, function settings, and secrets across Amplify Gen 2 sandboxes and branch deployments.
I classify a value before deciding where to store it. Browser-safe configuration can appear in a built JavaScript bundle. Server configuration belongs to a function or build environment. Credentials, signing keys, and provider tokens use a secret store and never enter source control.
Amplify Gen 2 has separate paths for function environment variables, function secrets, local sandbox values, and hosted branch settings. Using one .env file for all four creates confusion and increases the chance of shipping a credential.
Classify values by exposure
I label each value public, server-only, or secret. A public API base URL may be safe in the browser. A feature flag can be public or server-only depending on whether it reveals unreleased behavior. A database password, email-provider token, or webhook signing key is a secret.
The word "environment" does not make a value private. Next.js variables exposed to the client and values inserted during a frontend build can be read by users. I review the generated bundle when the boundary is unclear.
Use function environment values for non-secret settings
Function settings such as a mode name, safe endpoint, or log level can use the environment property. Amplify generates typed access through $amplify/env/<function-name>, which catches misspelled names during development.
The Amplify environment variables and secrets documentation warns that plain environment values can appear in build artifacts and CloudFormation events. I reserve them for values that are safe in those locations.
Use the secret mechanism for credentials
I define a named secret reference in the function resource and set its value for the sandbox or hosted branch. The function receives the value at runtime. I never copy the value into the schema, handler, test fixture, or Trello card.
Secret names stay stable across environments while values differ. That lets the same code call a test service in staging and the approved service in production without conditional credentials in source files.
Keep branches independent
Development, staging, and production receive their own configuration. I document which settings are shared and which must differ, including callback URLs, sender addresses, analytics destinations, and external API endpoints.
I check the target branch before changing a value. A console label is easy to misread, so the release checklist records the app ID, branch, and key name without recording the secret value.
Rotate and verify
A rotation is incomplete until the consumer uses the new value and the old value has been revoked. I update the target environment, deploy or restart the function if required, run a safe request, and confirm the provider saw the new credential. Then I remove the prior credential.
If a secret may have entered Git, deleting the file is not enough. I rotate the value and review repository history, build logs, artifacts, and any copied support messages.
Audit the boundary before release
I search the diff and tracked files for known key names, inspect frontend configuration, and verify that logs redact headers. I also test a missing-secret failure so the function reports configuration trouble without printing the value.
- Every value has an exposure class.
- Secrets use secret references.
- Branches have documented owners.
- Rotation includes revocation.
- Build and runtime logs are reviewed.
Need help with Amplify?
Terry Hunt Dev reviews cloud configuration and deployment boundaries through its AWS development service. If you need to separate browser settings from server secrets, describe the environments through the contact page without sending any credential values.