Follow Discord
Sweep 08 Oct 2026 · 18:53Z Build v2.1.295 516 read Stable v2.1.286 Latest v2.1.295 Next v2.1.295 Feeds RSS JSON llms.txt llms-full.txt Unofficial
One change · claude-code

Deploy Claude apps gateway on AWS changedclaude-apps-gateway-on-aws

Nearest release: v2.1.286, published 3 hours before upstream edited the page. Shown because the two are within 24 hours of each other. Nothing here says the release caused the edit.

Upstream edited this page at 30 Sep 2026 20:43 UTC, give or take a minute or two: the time comes from Anthropic’s own sitemap rather than from a commit. This site recorded the change at 30 Sep 2026 21:07 UTC.

Upstream edited
Recorded here
Lines+64added
Lines−1removed
From line 520 where the diff opens
First seen 14 Aug 2026 this site's first read of the page
Recorded edits10to this page, all time

## Cost attribution ### Per developer with `assume_role` ### Per team with application inference profiles

The whole hunk

from line 520, old and new numbered
/
lines
from line 520
520520 
521521### Spend
522522 
523Telemetry shows usage after the fact; [spend limits](/docs/en/claude-apps-gateway-spend-limits) are the gateway's live per-developer view and enforcement on top of the shared upstream credential.
523Telemetry shows usage after the fact; [spend limits](/docs/en/claude-apps-gateway-spend-limits) are the gateway's live per-developer view and enforcement.
524 
525## Cost attribution
526 
527The gateway signs every Bedrock request with its own principal, the ECS task role or EKS IRSA role, so by default AWS sees all of that spend under one IAM principal. There are two ways to split it in AWS's own billing data, and they combine.
528 
529### Per developer with `assume_role`
530 
531Create a second IAM role that holds the Bedrock permissions and trusts the gateway's principal, grant that principal `sts:AssumeRole` on it, and set [`assume_role`](/docs/en/claude-apps-gateway-config#per-developer-aws-cost-attribution) with `session_name: email` on the Bedrock upstream. The gateway then assumes that role once per developer per hour with the session name set to their email and signs their requests with the result. Requires a gateway running Claude Code v2.1.281 or later. The role can also be in another AWS account: see [Bedrock in another AWS account](/docs/en/claude-apps-gateway-config#bedrock-in-another-aws-account). In Terraform, next to the task role in the [Terraform bundle](#terraform-reference):
532 
533```hcl theme={null}
534resource "aws_iam_role" "bedrock_user" {
535 name = "claude-gateway-bedrock-user"
536 assume_role_policy = jsonencode({
537 Version = "2012-10-17"
538 Statement = [{ Effect = "Allow", Action = "sts:AssumeRole", Principal = { AWS = aws_iam_role.task.arn } }]
539 })
540}
541resource "aws_iam_role_policy" "bedrock_user_invoke" { # same Bedrock policy as the task role's
542 role = aws_iam_role.bedrock_user.id
543 policy = aws_iam_role_policy.bedrock_invoke.policy
544}
545resource "aws_iam_role_policy" "task_assume_bedrock_user" {
546 role = aws_iam_role.task.id
547 policy = jsonencode({
548 Version = "2012-10-17"
549 Statement = [{ Effect = "Allow", Action = "sts:AssumeRole", Resource = aws_iam_role.bedrock_user.arn }]
550 })
551}
552```
553 
554With `assume_role` set the gateway signs every Bedrock call, the free `CountTokens` call for spend metering included, with the assumed role's credentials, so the gateway's principal needs a Bedrock policy of its own only for an upstream without `assume_role`.
555 
556Because the gateway calls STS at request time, the private subnets need a path to `sts.<region>.amazonaws.com`. The NAT gateway from the prerequisites provides one, and so does an STS interface VPC endpoint that answers for that hostname. Each active developer costs one STS call per hour per gateway replica.
557 
558Each developer's requests reach AWS as the principal `arn:aws:sts::<account>:assumed-role/<role>/<email>`. To see spend per principal, use a billing export that includes IAM principal data; AWS's [IAM principal cost allocation](https://docs.aws.amazon.com/awsaccountbilling/latest/aboutv2/iam-principal-cost-allocation.html) page covers how to enable it and which billing tools show it.
559 
560### Per team with application inference profiles
561 
562This route uses only the [`models`](/docs/en/claude-apps-gateway-config#models) and [`managed`](/docs/en/claude-apps-gateway-config#managed) sections. Create one Bedrock [application inference profile](https://docs.aws.amazon.com/bedrock/latest/userguide/inference-profiles-create.html) per team and model, tag each profile with the team, and activate that tag as a cost allocation tag. Then give each team its own model id in `gateway.yaml` and pin each IdP group to its team's ids:
563 
564```yaml theme={null}
565models:
566 - id: platform-claude-opus-4-8
567 upstream_model:
568 bedrock: arn:aws:bedrock:us-east-1:123456789012:application-inference-profile/abc123
569 - id: data-claude-opus-4-8
570 upstream_model:
571 bedrock: arn:aws:bedrock:us-east-1:123456789012:application-inference-profile/def456
572managed:
573 policies:
574 - match: {groups: [team-platform]}
575 cli: {availableModels: [platform-claude-opus-4-8], enforceAvailableModels: true}
576 - match: {groups: [team-data]}
577 cli: {availableModels: [data-claude-opus-4-8], enforceAvailableModels: true}
578 - match: {}
579 cli: {availableModels: [claude-opus-4-8, claude-sonnet-4-6], enforceAvailableModels: true}
580```
581 
582Tell developers in a pinned team to start Claude Code with `--model platform-claude-opus-4-8`, using their team's id, because a session started without it runs the default model, which the gateway refuses for them.
583 
584The gateway enforces `availableModels` on every request, not only in the model picker, and AWS billing groups the spend by the tag you activated. Without the `match: {}` catch-all, a developer who matches no policy gets every model in the catalog and can bill either team's profile.
585 
586The costs: the config grows with teams times models, and the role that signs this upstream's Bedrock requests must also be allowed to invoke the `application-inference-profile/*` ARNs. That role is the gateway's principal, or with `assume_role` the role it assumes. See [`pricing`](/docs/en/claude-apps-gateway-config#pricing) for how the gateway's own spend meter prices these ids.
524587 
525588## Next steps
526589 
Feedback