Skip to content

feat(lambda-event-sources): add sqs provisioned poller config#36990

Open
kawaaaas wants to merge 15 commits intoaws:mainfrom
kawaaaas:feature/add-sqs-provisioned-poller-config
Open

feat(lambda-event-sources): add sqs provisioned poller config#36990
kawaaaas wants to merge 15 commits intoaws:mainfrom
kawaaaas:feature/add-sqs-provisioned-poller-config

Conversation

@kawaaaas
Copy link
Copy Markdown

Issue # (if applicable)

None

Reason for this change

Provisioned Mode for SQS Event Source Mappings is not yet supported in the L2 SqsEventSource construct. Users who want to use provisioned pollers must currently resort to L1 (CfnEventSourceMapping) or escape hatches, losing the benefit of type-safe props and built-in validation that L2 constructs provide.

Description of changes

Added provisionedPollerConfig property to SqsEventSourceProps, allowing users to configure minimumPollers and maximumPollers for SQS event source mappings.

Validation

  • minimumPollers: must be between 2 and 200 inclusive
  • maximumPollers: must be between 2 and 2,000 inclusive
  • minimumPollers must be ≤ maximumPollers
  • provisionedPollerConfig and maxConcurrency are mutually exclusive

The validation pattern follows the existing approach used for Kafka event sources.

Design decision
Although a ProvisionedPollerConfig interface already exists in both the aws-lambda module (event-source-mapping.ts) and the aws-lambda-event-sources module (stream.ts), this PR defines a separate SqsProvisionedPollerConfig interface within aws-lambda-event-sources (sqs.ts). This keeps the SQS-specific validation boundaries separate from stream sources, which may have different constraints. This separation of concerns avoids coupling SQS configuration to stream source behavior and makes it easier to evolve each independently.

Describe any new or updated permissions being added

None

Description of how you validated changes

Add both unit and integ tests

Checklist


By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license

@aws-cdk-automation aws-cdk-automation requested a review from a team February 14, 2026 04:26
@github-actions github-actions bot added p2 beginning-contributor [Pilot] contributed between 0-2 PRs to the CDK labels Feb 14, 2026
Copy link
Copy Markdown
Collaborator

@aws-cdk-automation aws-cdk-automation left a comment

Choose a reason for hiding this comment

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

(This review is outdated)

@aws-cdk-automation aws-cdk-automation dismissed their stale review February 14, 2026 04:39

✅ Updated pull request passes all PRLinter validations. Dismissing previous PRLinter review.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Feb 18, 2026

⚠️ Experimental Feature: This security report is currently in experimental phase. Results may include false positives and the rules are being actively refined.
Please try merge from main to avoid findings unrelated to the PR.


TestsPassed ✅SkippedFailed
Security Guardian Results48 ran48 passed
TestResult
No test annotations available

@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Feb 18, 2026

⚠️ Experimental Feature: This security report is currently in experimental phase. Results may include false positives and the rules are being actively refined.
Please try merge from main to avoid findings unrelated to the PR.


TestsPassed ✅SkippedFailed
Security Guardian Results with resolved templates48 ran48 passed
TestResult
No test annotations available

@aws-cdk-automation aws-cdk-automation added the pr/needs-community-review This PR needs a review from a Trusted Community Member or Core Team Member. label Mar 2, 2026
Copy link
Copy Markdown
Contributor

@badmintoncryer badmintoncryer left a comment

Choose a reason for hiding this comment

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

Thank you for your contribution! This PR looks almost good. I've add some minor comments.

Comment on lines +26 to +30
const app = new cdk.App({
postCliContext: {
'@aws-cdk/aws-lambda:useCdkManagedLogGroup': false,
},
});
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.

Is this feature flag needed?

Suggested change
const app = new cdk.App({
postCliContext: {
'@aws-cdk/aws-lambda:useCdkManagedLogGroup': false,
},
});
const app = new cdk.App();

Copy link
Copy Markdown
Author

@kawaaaas kawaaaas Mar 18, 2026

Choose a reason for hiding this comment

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

Thanks for pointing this out. I followed the same pattern as other integration tests in this directory (e.g., integ.sqs-null-filter.ts), which also sets postCliContext with @aws-cdk/aws-lambda:useCdkManagedLogGroup: false. I'm happy to remove it if you think consistency with those existing tests isn't necessary here — what would you prefer?

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.

This flag controls whether CDK auto-creates a LogGroup for Lambda. It's unrelated to Provisioned Pollers, so please just use new cdk.App(). The other tests likely just copied this pattern without need.

testCases: [stack],
});

app.synth();
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.

This line is not needed.

Suggested change
app.synth();

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Same as above — this follows the pattern in integ.sqs-null-filter.ts and other existing integration tests that include app.synth(). I can remove it if you'd like, but wanted to flag the existing convention. Let me know your preference and I'll align accordingly.

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.

app.synth() used to be required, but it became unnecessary a few years ago. For recent integ tests, please omit it.

Comment on lines +11 to +12
const fn = new TestFunction(this, 'F');
const queue = new sqs.Queue(this, 'Q', {
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.

nit: I think integration tests may also be referenced as working examples. In that case, having only Q or F written as an ID seems slightly problematic. Could you replace it with an appropriate CamelCase word?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Good point! I've updated the construct IDs to use descriptive CamelCase names. Please take a look.

}
if (this.props.provisionedPollerConfig) {
const { minimumPollers, maximumPollers } = this.props.provisionedPollerConfig;
if (minimumPollers !== undefined) {
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.

We should consider the case which the value is a token.

Suggested change
if (minimumPollers !== undefined) {
if (minimumPollers !== undefined && !Token.isUnresolved(minimumPollers)) {

Copy link
Copy Markdown
Author

@kawaaaas kawaaaas Mar 18, 2026

Choose a reason for hiding this comment

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

Addressed. The validation now skips checks when the value is an unresolved token, using Token.isUnresolved(). This applies to minimumPollers, maximumPollers, and the comparison between them. Please verify the implementation.

throw new ValidationError('Minimum provisioned pollers for SQS must be between 2 and 200 inclusive', queue);
}
}
if (maximumPollers !== undefined) {
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.

same as above. Please consider token case.

throw new ValidationError('Maximum provisioned pollers for SQS must be between 2 and 2000 inclusive', queue);
}
}
if (minimumPollers !== undefined && maximumPollers !== undefined) {
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.

Same as above. Please consider token case.

throw new ValidationError(`Maximum batch size must be between 1 and 10 inclusive (given ${this.props.batchSize}) when batching window is not specified.`, queue);
}
}
if (this.props.provisionedPollerConfig && this.props.maxConcurrency !== undefined) {
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.

The implementation is such that CDK does not throw an error when provisionedPollerConfig is an empty object {}. Is this acceptable? Is an actual deployment possible?
Personally, even if deployment with default values is possible, I feel it's not very intuitive that a configuration using an empty object is allowed.

Copy link
Copy Markdown
Author

@kawaaaas kawaaaas Mar 18, 2026

Choose a reason for hiding this comment

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

Thanks for raising this. According to the AWS Lambda API documentation, both MinimumPollers and MaximumPollers are marked as Required: No. So passing ProvisionedPollerConfig as an empty object should enable provisioned mode with Lambda's default values (minimumPollers: 2, maximumPollers: 200).

If we were to require at least one property, it would diverge from the API's actual behavior — users wouldn't be able to simply "enable provisioned mode with defaults" by passing provisionedPollerConfig: {}.

That said, I understand the concern about intuitiveness. As a middle ground, I've documented this behavior in the JSDoc for SqsProvisionedPollerConfig, noting that an empty object enables provisioned mode with Lambda's default values. Would that work, or would you prefer to enforce at least one property? I'll defer to your judgment here.

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.

I understand! It's ok to configure default value by passing {}.

if (this.props.provisionedPollerConfig && this.props.maxConcurrency !== undefined) {
throw new ValidationError('provisionedPollerConfig and maxConcurrency are mutually exclusive', queue);
}
if (this.props.provisionedPollerConfig) {
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.

Should we add a integer validation for minimum/maximumPollers?

Copy link
Copy Markdown
Author

@kawaaaas kawaaaas Mar 18, 2026

Choose a reason for hiding this comment

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

Added. The validation now uses Number.isInteger() to ensure minimumPollers and maximumPollers are integers. Please check the implementation.

@kawaaaas
Copy link
Copy Markdown
Author

@badmintoncryer
Thank you so much for taking the time to review this PR! I really appreciate the detailed and thoughtful feedback. I've addressed each comment below.

@badmintoncryer
Copy link
Copy Markdown
Contributor

@kawaaaas Thanks! I want you to update integ test and will approve this PR.

@kawaaaas
Copy link
Copy Markdown
Author

@badmintoncryer Thank you for the review! Updated the integ test and snapshot.

Copy link
Copy Markdown
Contributor

@badmintoncryer badmintoncryer left a comment

Choose a reason for hiding this comment

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

Thanks!

@nated0g
Copy link
Copy Markdown

nated0g commented Apr 1, 2026

Nice work! Would love to see this get merged. I went looking for this today and I guess I will need to use an escape hatch for now

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

beginning-contributor [Pilot] contributed between 0-2 PRs to the CDK p2 pr/needs-community-review This PR needs a review from a Trusted Community Member or Core Team Member.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants