Named Profiles & Multi-Account Config
Named profiles let one machine hold many AWS identities - separate accounts, separate roles - and switch between them by name.
Search across all documentation pages
Named profiles let one machine hold many AWS identities - separate accounts, separate roles - and switch between them by name.
A named profile is a labeled block of settings in the shared AWS files. Each profile is an independent identity.
Most real work spans more than one account: a dev account, a staging account, a production account. Profiles keep those identities side by side without re-running aws configure every time.
The layout is split across two files. Long-lived secrets go in ~/.aws/credentials. Everything else - region, output, role assumption, SSO - goes in ~/.aws/config.
The same profiles are visible to the CLI, boto3, and the AWS SDK for JavaScript v3. Configure once, use everywhere.
A common advanced pattern is a single base identity that assumes roles into other accounts, so you store one set of keys and reach many accounts.
Copy-paste the file layout, then select a profile three ways.
# ~/.aws/config
[default]
region = us-east-1
output = json
[profile staging]
region = us-east-1
output = json
[profile prod-readonly]
region = us-west-2
output = json# ~/.aws/credentials
[default]
aws_access_key_id = AKIA_DEFAULT
aws_secret_access_key = secret_default
[staging]
aws_access_key_id = AKIA_STAGING
aws_secret_access_key = secret_staging# Select a profile from the CLI
aws s3 ls --profile staging
# Or set it for the whole shell
export AWS_PROFILE=staging
aws sts get-caller-identityWhen to reach for this:
The same account selection in both SDKs, choosing a profile explicitly in code.
# --- Python (boto3) ---
import boto3
# A Session bound to a specific named profile.
session = boto3.Session(profile_name="staging")
sts = session.client("sts")
identity = sts.get_caller_identity()
print("staging account:", identity["Account"])
# A different profile, same process, no env changes.
prod_session = boto3.Session(profile_name="prod-readonly")
s3 = prod_session.client("s3")
buckets = s3.list_buckets()
print("prod buckets:", [b["Name"] for b in buckets["Buckets"]])// --- TypeScript (AWS SDK v3) ---
import { fromIni } from "@aws-sdk/credential-providers";
import { STSClient, GetCallerIdentityCommand } from "@aws-sdk/client-sts";
import { S3Client, ListBucketsCommand } from "@aws-sdk/client-s3";
// A credential provider bound to a specific named profile.
const sts = new STSClient({ credentials: fromIni({ profile: "staging" }) });
const identity = await sts.send(new GetCallerIdentityCommand({}));
console.log("staging account:", identity.Account);
// A different profile, same process, no env changes.
const s3 = new S3Client({
region: "us-west-2",
credentials: fromIni({ profile: "prod-readonly" }),
});
const buckets = await s3.send(new ListBucketsCommand({}));
console.log("prod buckets:", buckets.Buckets?.map((b) => b.Name));What this demonstrates:
Session(profile_name=...) in boto3 and fromIni({ profile }) in v3.fromIni supplies only credentials, so you pass region on the client.credentials file uses a bare header like [staging]; the config file uses [profile staging] (with the profile prefix).default - it is [default] in both files, never [profile default].output live in config; long-lived keys live in credentials. SSO and role settings live in config.Store one base identity and let a profile assume a role in another account.
# ~/.aws/config
[profile base]
region = us-east-1
[profile prod-admin]
role_arn = arn:aws:iam::222222222222:role/OrgAdmin
source_profile = base
region = us-east-1source_profile names the identity whose keys sign the AssumeRole request.role_arn is the role to assume in the target account.AssumeRole call automatically and cache the temporary credentials.mfa_serial = arn:aws:iam::...:mfa/you to require an MFA code on assumption.| Setting | File | Example |
|---|---|---|
| Access key / secret | ~/.aws/credentials | aws_access_key_id |
| Region / output | ~/.aws/config | region = us-east-1 |
role_arn / source_profile | ~/.aws/config | role assumption |
| SSO settings | ~/.aws/config | sso_session |
[profile staging] in the credentials file (or [staging] in config) makes the profile invisible. Fix: bare [name] in credentials, [profile name] in config; default is always bare.fromIni ignores region - fromIni returns only credentials, so a v3 client with no region throws a region error. Fix: pass region on the client, or set AWS_REGION.region to credentials has no effect. Fix: region belongs in config.source_profile - A role_arn profile with no source_profile (and no other base credentials) cannot sign the assume-role call. Fix: add source_profile or credential_source.~/.aws/credentials holds live secrets; a leaked commit is a breach. Fix: never place these files in a repo; keep them in the home directory only.--profile stagng yields a "profile not found" error, not a fallback to default. Fix: run aws configure list-profiles to confirm names.| Alternative | Use When | Don't Use When |
|---|---|---|
| IAM Identity Center (SSO) profiles | You have an org and want short-lived logins | You have no SSO setup and need a quick local key |
AWS_ACCESS_KEY_ID env vars | One-off scripts or CI with injected secrets | You juggle several accounts interactively |
Role assumption via role_arn | Cross-account access from one base identity | The accounts are unrelated with no trust set up |
| Separate CLI profiles per account | Interactive, human-driven multi-account work | Fully automated runtime inside AWS (use a role) |
It is a historical convention. The credentials file predates the config file, so config disambiguates its blocks with a profile prefix. The default profile is bare in both.
aws configure list-profilesIt reads both shared files and prints every profile name.
Yes. Create a separate boto3.Session(profile_name=...) or a separate v3 client with fromIni({ profile }) for each. They do not interfere.
In ~/.aws/config, inside that profile's block. Region is not a secret and does not belong in the credentials file.
It names the base identity whose long-lived keys sign the AssumeRole request for a role-based profile.
You need some base credentials that source_profile points to. Those can be static keys, an SSO session, or another assumed role.
fromIni supplies credentials only, not region. Pass region on the client or set AWS_REGION. The CLI reads region from the profile automatically.
Add mfa_serial = arn:aws:iam::123456789012:mfa/you to the role profile. The CLI and SDKs then prompt for or require an MFA token code.
For selection, effectively yes: AWS_PROFILE sets it for the whole shell, while --profile sets it for one command. Both pick a named profile from the shared files.
Yes. They are plain INI text. aws configure is just a convenience that writes the same format.
You get a "profile not found" error. There is no silent fallback to the default profile.
Yes. Both read ~/.aws/config and ~/.aws/credentials, so a profile you define once is usable from either SDK and the CLI.
Stack versions: This page was written for the AWS CLI v2, boto3 1.43.x (Python 3.10+), and the AWS SDK for JavaScript v3 (Node.js 18+).
Reviewed by Chris St. John·Last updated Jul 23, 2026