Skip to content

feat(apigatewayv2): add dedupeHandlers to reuse Integration + Function across routes#6914

Open
brentrager wants to merge 1 commit into
anomalyco:devfrom
SmooAI:feat/apigatewayv2-dedupe-handlers
Open

feat(apigatewayv2): add dedupeHandlers to reuse Integration + Function across routes#6914
brentrager wants to merge 1 commit into
anomalyco:devfrom
SmooAI:feat/apigatewayv2-dedupe-handlers

Conversation

@brentrager

Copy link
Copy Markdown

Closes #6913.

Problem

AWS HTTP APIs cap Integrations at 300 per API — and unlike the Routes quota (L-65B5C802, raisable to 1000+), the Integrations cap is hard, not adjustable via Service Quotas. Today every route() creates a new Integration + Lambda + Permission even when routes share the same handler, so splitting routes for clarity (different auth, rate limits, OpenAPI grouping) burns Integration slots. On large monorepos you hit 300 well before you have 300 distinct handlers. Same duplicate-resource-per-route class as #4559; aws-cdk fixed the analogue in aws/aws-cdk#12528.

Solution

Opt-in dedupeHandlers: true on ApiGatewayV2:

const api = new sst.aws.ApiGatewayV2("Api", { dedupeHandlers: true });
api.route("GET /a", "src/index.handler");
api.route("POST /b", "src/index.handler"); // reuses the Integration + Function + Permission

When set, the Nth route() against the same handler string reuses the first call's Integration + Function + Permission and only creates a new apigatewayv2.Route. Routes stay capped (default 300, raisable to 1000+); Integrations stay at exactly one per unique handler — the actual scaling ceiling. Default is false, so behavior is unchanged unless opted in.

URN stability

The route component keeps a stable URN across the dedup boundary (it does not spawn a separate shared-route component for routes 2-N). This means an existing app can flip dedupeHandlers: true without Pulumi seeing the route's parent URN change — which would otherwise make it try to create the new apigatewayv2.Route before deleting the old one and fail with ConflictException ("Route with key X already exists").

Notes

  • ~176 lines across apigatewayv2.ts + apigatewayv2-lambda-route.ts. Typechecks clean (tsc --noEmit).
  • Production-tested: this powered a ~370-route HTTP API under the 300-integration cap.
  • apigatewayv2 has no existing tests in platform/test/components/. Happy to add a synth-based test asserting "N routes / same handler → 1 Integration" if you'd like it for this PR — just didn't want to introduce a bespoke pattern unprompted.

…n across routes

AWS HTTP APIs cap Integrations per API at 300 — a hard cap that is NOT
adjustable through Service Quotas (only Routes are, via L-65B5C802). Today
every route() call creates a new Integration + Lambda + Permission even when
the handler string is identical, so splitting routes for clarity (different
auth, rate limits, etc.) burns Integration slots unnecessarily. On large
monorepos this is the real scaling ceiling people hit.

Add an opt-in `dedupeHandlers: true` flag on ApiGatewayV2. When set, the Nth
route() call against the same handler string reuses the first call's
Integration + Function + Permission and only creates a new apigatewayv2.Route.
Routes stay capped (default 300, raisable to 1000+) but Integrations stay at
exactly one per unique handler.

The route component keeps a stable URN across the dedup boundary (no separate
shared-route component), so migrating an existing app from non-dedup state
doesn't make Pulumi recreate routes and hit ConflictException at API Gateway.

Refs anomalyco#4559 (duplicate per-route resources). Same approach aws-cdk took
in aws/aws-cdk#12528 (dedupe HTTP integrations per route).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

ApiGatewayV2: a new Integration is created per route, hitting the hard 300-integration cap

1 participant