Skip to content
GitHubXDiscordRSS

AWS Credential Overrides

Alchemy supports deploying resources to multiple AWS accounts and regions in a single deployment. This enables complex multi-account architectures and cross-account resource management from a single codebase.

The AWS credential override system in Alchemy provides a flexible three-tier approach to credential management:

  1. Global Level: Default credentials from environment variables
  2. Scope Level: Credentials specified in alchemy.run() options
  3. Resource Level: Credentials specified in individual resource properties

This hierarchical approach allows for precise control over which credentials are used for each resource, enabling multi-account deployments where resources can be created in different AWS accounts as needed.

The following credential properties can be specified at any level:

PropertyTypeDescriptionEnvironment Variable
regionstringAWS region (e.g., “us-east-1”)AWS_REGION, AWS_DEFAULT_REGION
profilestringAWS profile name from credentials fileAWS_PROFILE
roleArnstringARN of IAM role to assumeAWS_ROLE_ARN
roleSessionNamestringSession name for assumed roleAWS_ROLE_SESSION_NAME
accessKeyIdSecretAWS access key IDAWS_ACCESS_KEY_ID
secretAccessKeySecretAWS secret access keyAWS_SECRET_ACCESS_KEY
sessionTokenSecretAWS session token (for temporary credentials)AWS_SESSION_TOKEN
externalIdstringExternal ID when assuming a roleAWS_EXTERNAL_ID

Global Level Credentials (Environment Variables)

Section titled “Global Level Credentials (Environment Variables)”

The simplest way to provide AWS credentials is through environment variables:

Terminal window
export AWS_REGION=us-west-2
export AWS_PROFILE=production

These credentials will be used by default for all AWS resources unless overridden at the scope or resource level.

You can also specify AWS credentials when creating the main application scope:

import { alchemy } from "alchemy";
import { Vpc } from "alchemy/aws/ec2";
const app = await alchemy("my-app", {
aws: {
region: "us-west-2",
profile: "production",
},
});
// All resources will use the specified credentials by default
const vpc = await Vpc("main-vpc", {
cidrBlock: "10.0.0.0/16",
tags: { Name: "main-vpc" }
});

You can override credentials for specific resources by providing credential properties directly in the resource options:

import { Vpc } from "alchemy/aws/ec2";
// Create a VPC in one account
const mainVpc = await Vpc("main-vpc", {
cidrBlock: "10.0.0.0/16",
profile: "main-account",
region: "us-west-2",
tags: { Name: "main-vpc" }
});
// Create a VPC in another account
const secondaryVpc = await Vpc("secondary-vpc", {
cidrBlock: "10.1.0.0/16",
profile: "secondary-account",
region: "us-east-1",
tags: { Name: "secondary-vpc" }
});

You can assume an IAM role in another account for cross-account access:

import { Vpc } from "alchemy/aws/ec2";
// Create a VPC using role assumption
const vpc = await Vpc("cross-account-vpc", {
cidrBlock: "10.0.0.0/16",
roleArn: "arn:aws:iam::123456789012:role/DeploymentRole",
roleSessionName: "alchemy-deployment",
region: "us-west-2",
tags: { Name: "cross-account-vpc" }
});

When providing sensitive credentials like access keys, always use alchemy.secret() to ensure they are properly encrypted:

import { alchemy } from "alchemy";
import { Vpc } from "alchemy/aws/ec2";
// Resource-level credentials with secrets
const vpc = await Vpc("secure-vpc", {
cidrBlock: "10.0.0.0/16",
accessKeyId: alchemy.secret(process.env.AWS_ACCESS_KEY_ID!),
secretAccessKey: alchemy.secret(process.env.AWS_SECRET_ACCESS_KEY!),
sessionToken: alchemy.secret(process.env.AWS_SESSION_TOKEN!),
region: "us-west-2",
tags: { Name: "secure-vpc" }
});
// Scope-level credentials with secrets
await alchemy.run("production", {
aws: {
accessKeyId: alchemy.secret(process.env.PROD_AWS_ACCESS_KEY_ID!),
secretAccessKey: alchemy.secret(process.env.PROD_AWS_SECRET_ACCESS_KEY!),
region: "us-west-2"
}
}, async () => {
// All AWS resources inherit the encrypted credentials
const vpc = await Vpc("prod-vpc", {
cidrBlock: "10.0.0.0/16",
tags: { Name: "prod-vpc" }
});
});

You can specify AWS credentials for a specific scope using the alchemy.run() options:

import { alchemy } from "alchemy";
import { Vpc } from "alchemy/aws/ec2";
await alchemy.run("production", {
// Scope-level AWS credential overrides
aws: {
region: "us-east-1",
profile: "production-account",
},
}, async () => {
// Resources created here will use the production-account profile
// and us-east-1 region by default
const vpc = await Vpc("main-vpc", {
cidrBlock: "10.0.0.0/16",
tags: { Name: "main-vpc" }
});
});

When resolving AWS credentials, Alchemy follows this order of precedence:

  1. Resource-level credentials (highest priority)
  2. Scope-level credentials (from alchemy.run() options)
  3. Global-level credentials (from environment variables)

The following AWS resources support credential overrides:

  • VPC
  • Subnet
  • Internet Gateway
  • Internet Gateway Attachment
  • Security Group
  • NAT Gateway
  • Route Table
  • Route
  1. Use profiles instead of hard-coded credentials whenever possible
  2. Be consistent with regions within related resources
  3. Use the minimum required permissions for each account
  4. Document which resources deploy to which accounts for clarity
  5. Test multi-account deployments thoroughly before using in production
  • “Profile not found”: Ensure the specified profile exists in your AWS credentials file
  • “Access denied”: Check that the credentials have the necessary permissions
  • “Resource not found”: Verify you’re using the correct region for lookups
  • “Invalid credentials”: Ensure credentials are correctly formatted and not expired
  • Set AWS_SDK_LOAD_CONFIG=1 to ensure the SDK loads config from the AWS config file
  • Use AWS_PROFILE environment variable to set a default profile for testing
  • Check AWS CloudTrail logs to see which credentials were used for API calls