Skip to content

feat(circuit_breaker): support composite primary key in DynamoDB persistence#8316

Merged
leandrodamascena merged 4 commits into
aws-powertools:developfrom
Iamrodos:feat/circuit-breaker-composite-key
Jul 2, 2026
Merged

feat(circuit_breaker): support composite primary key in DynamoDB persistence#8316
leandrodamascena merged 4 commits into
aws-powertools:developfrom
Iamrodos:feat/circuit-breaker-composite-key

Conversation

@Iamrodos

@Iamrodos Iamrodos commented Jul 1, 2026

Copy link
Copy Markdown
Contributor

Issue number: closes #8315

Summary

Changes

CircuitBreakerDynamoDBPersistence lets you rename attributes but assumes a partition-key-only table. Against a single-table design that uses a composite (partition + sort) key, DynamoDB requires the sort key on every call, so the layer can't operate: it fails open on every invocation (logged at WARNING) and the breaker never trips.

This adds optional sort_key_attr and static_pk_value parameters, matching the composite-key support the Idempotency utility already offers, so there's nothing new to learn for anyone using both. Set sort_key_attr and the circuit name is written to the sort key, with static_pk_value in the partition key (default circuit_breaker#{LAMBDA_FUNCTION_NAME}, which namespaces circuits per function; set it to a fixed value to share one circuit across functions). Omit sort_key_attr and behavior is unchanged — the circuit name stays the partition key, exactly as today.

The composite key is threaded through every DynamoDB path the utility uses, not just the read: the get_item read, the conditional put_item that elects the single half-open probe, and the update_item on state transitions. So the breaker works end to end on a composite table.

Also included: docs (docs/utilities/circuit_breaker.md) with a "Using a composite primary key" section, a sample-item table, and share-vs-namespace guidance; and a new example, examples/circuit_breaker_alpha/src/working_with_composite_key.py.

User experience

Before, a composite-key table couldn't be reused — every call failed and the circuit never tripped:

# Fails open on every invocation against a PK + SK table
persistence = CircuitBreakerDynamoDBPersistence(table_name="my-single-table")

Now you opt into the existing single-table layout:

persistence = CircuitBreakerDynamoDBPersistence(
    table_name="my-single-table",
    key_attr="PK",
    sort_key_attr="SK",
    static_pk_value="CIRCUIT_BREAKER",
)

Omitting sort_key_attr keeps today's partition-key-only behavior, so this is fully backward compatible.

Validation

New Stubber-based functional tests cover get_item / put_item / conditional put_item / update_item in both single-key and composite modes, and assert the read-back name comes from the sort key in composite mode. They also cover the sort_key_attr == key_attr guard and the namespaced default value.

poetry run pytest tests/functional/circuit_breaker_alpha tests/unit/circuit_breaker_alpha

By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.

Disclaimer: We value your time and bandwidth. As such, any pull requests created on non-triaged issues might not be successful.

…istence

Add optional `sort_key_attr` and `static_pk_value` parameters to
CircuitBreakerDynamoDBPersistence so circuit state can be stored in a
single-table (composite key) design, mirroring the Idempotency utility.

When `sort_key_attr` is set, the circuit name is written to the sort key
and `static_pk_value` to the partition key (default
`circuit_breaker#<function-name>`); omit it for the current
partition-key-only behavior. The composite key is threaded through the
get, conditional put (half-open probe election) and update paths.

Includes Stubber-based tests for both modes, docs, and an example.

Closes aws-powertools#8315
@Iamrodos Iamrodos requested a review from a team as a code owner July 1, 2026 22:51
@Iamrodos Iamrodos requested a review from leandrodamascena July 1, 2026 22:51
@boring-cyborg boring-cyborg Bot added documentation Improvements or additions to documentation tests labels Jul 1, 2026
@powertools-for-aws-oss-automation powertools-for-aws-oss-automation Bot added the size/L Denotes a PR that changes 100-499 lines, ignoring generated files. label Jul 1, 2026

@leandrodamascena leandrodamascena left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Really nice work. One small thing: static_pk_value only does anything when sort_key_attr is set. If someone passes it alone it's silently ignored, which is annoying to debug. Could we warn?

if static_pk_value is not None and sort_key_attr is None:
    warnings.warn(
        "static_pk_value is ignored unless sort_key_attr is also set.",
        category=PowertoolsUserWarning,
        stacklevel=2,
    )

@Iamrodos

Iamrodos commented Jul 2, 2026

Copy link
Copy Markdown
Contributor Author

Checking errors. Duplicated file name for the example. Fixing.

…sename so mypy no longer clashes with the idempotency example.
@powertools-for-aws-oss-automation powertools-for-aws-oss-automation Bot added size/L Denotes a PR that changes 100-499 lines, ignoring generated files. and removed size/L Denotes a PR that changes 100-499 lines, ignoring generated files. labels Jul 2, 2026
@Iamrodos

Iamrodos commented Jul 2, 2026

Copy link
Copy Markdown
Contributor Author

Really nice work. One small thing: static_pk_value only does anything when sort_key_attr is set. If someone passes it alone it's silently ignored, which is annoying to debug.

Yes, it came up in my own reviews and I skipped doing in. Serves me right. Will also add a test like there already is for the other guards. Doing now.

…rt_key_attr since it is otherwise silently ignored.
@codecov

codecov Bot commented Jul 2, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 96.63%. Comparing base (5535469) to head (775f797).

Additional details and impacted files
@@           Coverage Diff            @@
##           develop    #8316   +/-   ##
========================================
  Coverage    96.63%   96.63%           
========================================
  Files          296      296           
  Lines        14689    14704   +15     
  Branches      1231     1235    +4     
========================================
+ Hits         14194    14209   +15     
  Misses         360      360           
  Partials       135      135           

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@powertools-for-aws-oss-automation powertools-for-aws-oss-automation Bot added size/L Denotes a PR that changes 100-499 lines, ignoring generated files. and removed size/L Denotes a PR that changes 100-499 lines, ignoring generated files. labels Jul 2, 2026
@powertools-for-aws-oss-automation powertools-for-aws-oss-automation Bot added size/L Denotes a PR that changes 100-499 lines, ignoring generated files. and removed size/L Denotes a PR that changes 100-499 lines, ignoring generated files. labels Jul 2, 2026
@sonarqubecloud

sonarqubecloud Bot commented Jul 2, 2026

Copy link
Copy Markdown

@leandrodamascena leandrodamascena left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks a lot for addressing it @Iamrodos! APPROVED!

@leandrodamascena leandrodamascena merged commit cb6f906 into aws-powertools:develop Jul 2, 2026
18 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation size/L Denotes a PR that changes 100-499 lines, ignoring generated files. tests

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Feature request: Circuit breaker DynamoDB persistence, support single-table (composite key) reuse

2 participants