serverless
serverless.yml
AccountId
configuration
AWS Lambda

How do I get the AccountId as a variable in a serverless.yml file?

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

In Serverless Framework projects, the AWS account ID often appears in IAM policies, ARNs, environment variables, or resource names. Hardcoding it into serverless.yml is fragile because the same service usually deploys to more than one AWS account over time. A better approach is to resolve the account ID dynamically from the active credentials and reuse it through the configuration.

Resolve the Account ID Once

Serverless can expose the current AWS account ID through the built-in AWS variable source. A clean pattern is to store it under custom and reference that one value everywhere else.

yaml
1service: billing-api
2frameworkVersion: '3'
3
4provider:
5  name: aws
6  runtime: nodejs20.x
7  region: us-east-1
8
9custom:
10  accountId: ${aws:accountId}
11
12functions:
13  hello:
14    handler: handler.hello
15    environment:
16      AWS_ACCOUNT_ID: ${self:custom.accountId}

This keeps the source of truth in one place and makes the rendered configuration easier to inspect.

Reuse It in IAM and Resource Names

Once the account ID is available as a variable, you can safely incorporate it into ARNs or names that must stay unique across accounts.

yaml
1provider:
2  iam:
3    role:
4      statements:
5        - Effect: Allow
6          Action:
7            - s3:GetObject
8          Resource:
9            - arn:aws:s3:::my-bucket-${self:provider.stage}-${self:custom.accountId}/*
10
11resources:
12  Resources:
13    AuditQueue:
14      Type: AWS::SQS::Queue
15      Properties:
16        QueueName: audit-${self:provider.stage}-${self:custom.accountId}

This is much safer than repeating a literal account number in multiple places and hoping none of them drift.

Verify the Rendered Configuration Before Deploying

Dynamic variables are only helpful if they resolve to what you expect. Before a deploy, inspect the final configuration:

bash
sls print --stage dev --region us-east-1

That shows the resolved serverless.yml after variables are evaluated. You can also compare the result to AWS CLI output:

bash
aws sts get-caller-identity --query Account --output text

If those do not match, you are likely using different credentials or profiles between the two tools.

Make Stage and Profile Selection Explicit

Multi-account deployments are safer when the profile used for a given stage is explicit. Otherwise, a default local profile can quietly point at the wrong account.

yaml
1provider:
2  name: aws
3  stage: ${opt:stage, 'dev'}
4  profile: ${param:awsProfile, 'dev-profile'}
5
6params:
7  dev:
8    awsProfile: dev-profile
9  prod:
10    awsProfile: prod-profile
11
12custom:
13  accountId: ${aws:accountId}

That makes the deployment target more visible in both logs and reviews.

Support Controlled Overrides in CI

Some teams want CI to pass the expected account ID explicitly for extra safety. You can allow that while keeping dynamic lookup as the default.

yaml
custom:
  accountId: ${param:accountId, aws:accountId}

Then a pipeline can supply the value when needed:

bash
sls deploy --param="accountId=123456789012"

This is useful when you want a pipeline to fail fast if the account context is not what you expected.

Troubleshoot Resolution Failures

If ${aws:accountId} does not resolve, the problem is usually not YAML syntax. The more common causes are missing credentials, the wrong profile, or an environment mismatch between local shell variables and the Serverless process.

The quickest troubleshooting loop is:

  1. run sls print
  2. run aws sts get-caller-identity
  3. compare the active profile, region, and environment variables

That usually reveals whether the configuration or the AWS credential context is the real issue.

Common Pitfalls

The biggest pitfall is hardcoding account IDs in several different places. That works in the first environment and becomes a maintenance problem as soon as the service moves across accounts.

Another common issue is trusting the default AWS profile without checking which credentials Serverless is actually using. Dynamic lookup is only safe if the credentials are the ones you intended.

Teams also skip sls print, which removes the easiest pre-deployment validation step available in Serverless Framework.

Summary

  • Use ${aws:accountId} to resolve the current AWS account dynamically in serverless.yml.
  • Store it once under custom and reference that variable everywhere else.
  • Validate the rendered configuration with sls print before deploying.
  • Make stage-to-profile mapping explicit in multi-account setups.
  • Add a parameter override only if your CI workflow needs a controlled safety check.

Course illustration
Course illustration

All Rights Reserved.