On this page · 11 sections
- What actually changed
- The trap: your policies already changed meaning
- The condition key that silently fails
- CloudFormation will fail before your policies do
- What it costs, and what the tags will not tell you
- Who is affected, and how to tell if that is you
- India-specific considerations
- What is still unknown
- FAQ
- How eCorpIT can help
- References
Summary. AWS announced attribute-based access control (ABAC) for Amazon DynamoDB Streams on 19 August 2026, in all commercial AWS Regions and AWS GovCloud (US). You can now attach up to 50 tags to each stream, with a 10 KB ceiling across all tags on that stream, and gate GetRecords, DescribeStream and GetShardIterator on aws:ResourceTag. The part the announcement leaves out matters more: for existing customers the feature is off by default, turning it on is an account-and-Region decision, and you can reverse it only within seven calendar days. Before you enable it, every aws:ResourceTag condition that touches a stream ARN evaluates as though the stream carries no tags at all. On the day you flip it, those same conditions start matching real tags, and both Allow and Deny statements change outcome without anyone editing a policy. The DynamoDB Streams read path itself still bills at $0.0000002 per read request unit beyond the first 2.5 million units a month in US East (N. Virginia), effective 1 August 2026 in the AWS Price List API, and the tags you are about to attach will not split that number for you.
What actually changed
The AWS What's New post frames this as a simplification: fewer IAM policies to manage access across teams and environments. The mechanics in the DynamoDB Developer Guide are narrower than that framing suggests.
Stream resources do not inherit tags from their parent table. You tag the stream ARN directly, in the form arn:aws:dynamodb:*:*:table/*/stream/*, and you manage those tags independently of the table's. Indexes still inherit table tags; streams never did and still do not. So a team that already tags every table with CostCenter and environment starts this migration with zero tagged streams, and any policy written against stream ARNs on the assumption of inheritance will deny.
Three condition keys work, and they are the AWS global keys, not DynamoDB's own: aws:ResourceTag/tag-key, aws:RequestTag/tag-key and aws:TagKeys. They apply to TagResource, UntagResource and to read APIs including GetRecords.
| Property | DynamoDB tables ABAC | DynamoDB Streams ABAC |
|---|---|---|
| Tag inheritance | Indexes inherit the table's tags | Streams inherit nothing from the parent table |
| Max tags per resource | 50 | 50 |
| Max total tag size | 10 KB per table | 10 KB per stream |
| Default state, existing accounts | Enabled for most accounts | Disabled until you opt in |
| Enablement scope | Per account, per Region | Per account, per Region, separate from tables |
| Self-service opt-out window | Seven calendar days | Seven calendar days |
The last row of that table is the one to write down. Enabling ABAC for tables does not enable it for streams. They are two independent switches, and the Developer Guide states so explicitly.
The trap: your policies already changed meaning
This is the failure mode nobody will find in the announcement. The Developer Guide is blunt about it: "When DynamoDB Streams ABAC is not enabled for your account, aws:ResourceTag conditions are evaluated as if no tags are attached to the stream resource."
Read that twice, then read it once as an Allow and once as a Deny.
As an Allow, a statement permitting GetRecords on arn:aws:dynamodb:*:*:table/*/stream/* when aws:ResourceTag/Team equals Analytics currently denies everything, because no stream ever matches. AWS documents exactly this in Example 1: without Streams ABAC the DescribeStream call returns AccessDeniedException; with it enabled, the same call succeeds. Nothing in the policy changed. The account-level switch did.
As a Deny, the reversal is worse, and it is the one that breaks production. A broad guardrail written against arn:aws:dynamodb:*:*:* with a tag condition has, until now, never matched a stream. After you enable Streams ABAC it starts matching, and consumers that have been reading a stream for two years begin failing with AccessDeniedException. AWS's own pre-flight checklist tells you to hunt for precisely this shape: wildcard resource ARNs carrying tag-based conditions that "might unintentionally apply to streams."
The audit AWS asks for before you enable is three greps across every identity-based policy, resource-based policy and service control policy in the account:
aws:ResourceTagconditions on stream ARNs (table/*/stream/*).
aws:RequestTagoraws:TagKeysconditions paired withdynamodb:TagResourceordynamodb:UntagResource.
- Wildcard
dynamodb:*:*:*resources with any tag condition attached.
Do it in a non-production account first. The opt-out is seven calendar days, self-service only through the console, and only if you opted in through the console. If Streams ABAC was turned on for your account through AWS Support, the Developer Guide says you cannot reverse it in the console at all — you have to go back to Support.
The condition key that silently fails
DynamoDB has a service-specific dynamodb:ResourceTag condition key. It does not work for streams.
The troubleshooting page documents the exact error: a policy allowing GetRecords with "dynamodb:ResourceTag/Team": "Analytics" fails with AccessDeniedException, because service-specific condition keys "aren't considered as valid condition keys" here. The fix is a one-word edit to aws:ResourceTag/Team. The reason this will bite people is that copy-paste from an existing table policy is the obvious way to write the first stream policy, and the failure looks identical to a missing permission rather than a wrong key.
Two other operational details from the same page. Streams ABAC status updates are asynchronous and tag evaluation is eventually consistent, so a policy that should work may not for a few minutes after you enable. And after a parent table is deleted, the stream lives on for 24 hours; during that window you can still tag or untag it, but only with the CLI or SDK tag-resource, untag-resource and list-tags-of-resource commands against the stream ARN. The console and CloudFormation cannot touch it. Past 24 hours you get ResourceNotFoundException.
CloudFormation will fail before your policies do
For most teams the first symptom will not be an access denial. It will be a red stack.
CloudFormation now propagates stack-level tags to stream resources automatically, in addition to any tags you set explicitly under StreamSpecification.Tags for AWS::DynamoDB::Table or under ReplicaStreamSpecification.Tags for AWS::DynamoDB::GlobalTable. If your deployment role does not hold dynamodb:TagResource and dynamodb:UntagResource on arn:aws:dynamodb:*:*:table/*/stream/*, the deployment fails. This affects stacks that never mention stream tags, because inherited stack tags are enough to trigger the call.
The Developer Guide adds dynamodb:ListTagsOfResource to the list of permissions a CloudFormation service role should carry for stream resources. Add all three in the same change, before you enable ABAC, and roll it through your pipeline as a normal deployment-role update rather than as an emergency fix at 2 a.m.
Teams running scoped, plan-derived deploy permissions will recognise the pattern from IAM policy generation against Terraform plan files: a new resource type appears inside an existing resource's lifecycle, and the least-privilege policy that was correct last month is now short by two actions.
What it costs, and what the tags will not tell you
Here the DynamoDB documentation contradicts itself, and the contradiction has a billing consequence.
The tagging page still carries this note: "Currently, DynamoDB Streams usage cannot be tagged." The ABAC pages, published the same week, describe attaching up to 50 tags to a stream and using them in IAM conditions. Both are true, and reconciling them is the practical point: stream tags exist for authorization, not for cost allocation. Tagging a stream CostCenter: 12345 will gate who can call GetRecords on it. It will not produce a CostCenter line for that stream's usage in Cost Explorer.
That usage is not free. From the AWS Price List API for AmazonDynamoDB in us-east-1, effective 1 August 2026:
| Line item | Usage type | Price |
|---|---|---|
| DynamoDB Streams read request units, free tier | USE1-Streams-Requests | $0.00 for the first 2.5 million per month |
| DynamoDB Streams read request units, beyond free tier | USE1-Streams-Requests | $0.0000002 per unit, or $0.20 per million |
| Change data capture units for Kinesis Data Streams | USE1-ChangeDataCaptureUnits-Kinesis | $0.10 per million |
A Lambda consumer polling a busy stream generates GetRecords calls whether or not records are returned, so the read-request line is driven by poll frequency and shard count as much as by write volume. If your FinOps model assumed stream tags would finally break that number out by team, it will not. The chargeback story still has to be reconstructed from table-level tags and shard topology.
The honest engineering read: this launch is a security control, and treating it as a cost-allocation feature will waste a sprint.
Who is affected, and how to tell if that is you
You are exposed if any of the following is true:
- You have an AWS account created before 19 August 2026 that uses DynamoDB Streams and any tag-based IAM condition anywhere in its policy set.
- You run CloudFormation or CDK stacks with stack-level tags that create
AWS::DynamoDB::TableorAWS::DynamoDB::GlobalTableresources with streams enabled.
- You use service control policies with wildcard DynamoDB resources and tag conditions, which will now reach stream ARNs across every account in the organisational unit.
- You have copied
dynamodb:ResourceTagconditions from table policies into anything that touches a stream.
You are not exposed, today, if Streams ABAC is off and you never enable it. Off is not a permanent answer — AWS has enabled table ABAC by default for most accounts, and the same trajectory for streams is the obvious one, but it does buy you the time to run the audit properly.
Checking status is less obvious than it should be. You need dynamodb:GetAbacStatus to read it and dynamodb:UpdateAbacStatus to change it, and the console's "Attribute-based access control for Streams" card appears on the Settings page only if you have a DynamoDB table in the current Region. With no table in the Region, the card's absence tells you nothing. With a table present, no card means enabled. That is a genuinely confusing detection rule, and it is worth scripting GetAbacStatus across every Region rather than clicking through the console.
India-specific considerations
For teams operating under the Digital Personal Data Protection Act 2023, DynamoDB Streams are frequently the path by which personal data leaves the table of record and reaches search indexes, analytics stores and third-party processors. Until now, restricting who could read that flow meant enumerating stream ARNs by name in IAM policies, which does not survive table recreation because the stream ARN carries a timestamp suffix. Tag-based conditions survive it, provided the tag is reapplied at creation, which is exactly what the CloudFormation StreamSpecification.Tags property now does.
That makes Streams ABAC a genuine improvement for purpose-limitation controls, and worth pairing with the wider cloud security posture management sweep most Indian enterprises are already running. The audit work is the same work: find every tag condition, decide what it should mean, then flip the switch.
What is still unknown
Three things the documentation does not settle.
The What's New post says the capability is available in all commercial Regions and GovCloud (US), but AWS does not publish which existing accounts fall into the "most AWS accounts" bucket that gets it enabled by default versus the "existing customers" bucket that does not. There is no documented cutoff date. GetAbacStatus is the only reliable answer.
The Service Authorization Reference page for DynamoDB does not render GetAbacStatus or UpdateAbacStatus without JavaScript, so the canonical action list for these two new IAM actions is currently only readable in the Developer Guide.
And the Tagging.html note that stream usage cannot be tagged has not been updated alongside the ABAC pages. Until AWS reconciles them, assume cost allocation for streams is unchanged.
FAQ
How eCorpIT can help
Auditing an entire policy set for tag conditions that will change meaning is exactly the kind of work that gets deferred until something breaks. Our senior engineering teams run IAM policy audits, deployment-role scoping and CloudFormation remediation as a single piece of work across AWS accounts and Regions, and we are ISO 27001:2022 certified and assessed at CMMI Level 5. If you run DynamoDB Streams in production and want the audit done before the switch is flipped, contact us.
References
- Amazon DynamoDB Streams now supports attribute-based access control. AWS What's New, 19 August 2026.
- Using attribute-based access control with DynamoDB Streams. Amazon DynamoDB Developer Guide.
- Enabling ABAC for DynamoDB Streams. Amazon DynamoDB Developer Guide.
- Using ABAC with DynamoDB Streams. Amazon DynamoDB Developer Guide.
- Troubleshooting common ABAC errors for DynamoDB Streams. Amazon DynamoDB Developer Guide.
- Example 1: Allow stream read access using aws:ResourceTag. Amazon DynamoDB Developer Guide.
- Example 2: Allow tagging a stream using aws:RequestTag. Amazon DynamoDB Developer Guide.
- Example 4: Tagging streams using CloudFormation. Amazon DynamoDB Developer Guide.
- Using attribute-based access control with DynamoDB. Amazon DynamoDB Developer Guide.
- Enabling ABAC in DynamoDB. Amazon DynamoDB Developer Guide.
- Adding tags and labels to resources in DynamoDB. Amazon DynamoDB Developer Guide.
- TagResource API reference. Amazon DynamoDB API Reference.
- DescribeStream API reference. Amazon DynamoDB Streams API Reference.
- AWS Price List API, AmazonDynamoDB offer, us-east-1. effective 1 August 2026.
- Working with DynamoDB Streams. Amazon DynamoDB Developer Guide.
Last updated: 22 August 2026.