Skip to content

feat: AppSync Lambda BatchInvoke support (createAppSyncBatchHandler + maxBatchSize) - #388

Merged
hoegertn merged 4 commits into
mainfrom
feat/appsync-batch-invoke
Oct 20, 2026
Merged

hoegertn merged 4 commits into
mainfrom
feat/appsync-batch-invoke

Conversation

@hoegertn

Copy link
Copy Markdown
Contributor

Closes #387.

Adds first-class AppSync Lambda BatchInvoke support. Two additive, backward-compatible pieces.

createAppSyncBatchHandler

New factory createAppSyncBatchHandler<T, R, S> in src/lambda/handler.ts, returning an AWSLambda.AppSyncBatchResolverHandler<T, R, S>. Array of events in, R[] out in source order. It mirrors createAppSyncHandler's context and auth plumbing but operates over a batch:

  • Authenticates once per batch off events[0] with a fresh AppSyncCognitoAuthorizer, same logger metadata as the single handler.
  • Context AppSyncBatchHandlerContext<T, S> extends AppSyncHandlerContext<T> and exposes both ctx.event (= events[0]) and the full ctx.events, so existing handler code that reads ctx.event.arguments keeps compiling.
  • Reuses the createAppSyncHandler: support typed errors so expected failures return GraphQL errors without failing the Lambda invocation #385 typed-error model. The inline catch logic was refactored out of createAppSyncHandler into shared toTypedError / buildErrorEnvelope helpers so both handlers run one error path and cannot drift.

maxBatchSize on addLambdaResolver

New optional argument LambdaResolverOptions { maxBatchSize?: number } on GraphQlApi.addLambdaResolver in src/constructs/graphql.ts. When set, the default UNIT resolver gets MaxBatchSize, the BatchInvoke request template MappingTemplate.lambdaRequest('$utils.toJson($context)', 'BatchInvoke'), and the lambdaResult() response template. Unset keeps today's exact single-invoke shape. Combining maxBatchSize with typedErrors throws before any resource is created, since the BatchInvoke templates have no equivalent on the APPSYNC_JS pipeline resolver.

Error semantics

Batch errors are fail-whole-batch by design. A thrown typed error returns one identical envelope per event (AppSync's BatchInvoke contract expects one result per event); a plain Error always rethrows. This matches the single handler. A caller wanting per-event partial success catches inside its own ctx.events.map.

Compatibility

Fully additive. New export createAppSyncBatchHandler and a new optional arg on addLambdaResolver. Existing single-item resolvers are untouched, verified byte-for-byte via Match.absent() assertions on the no-options resolver.

Testing

  • npm run build (compile + jest + package): green.
  • npm run test: 14 suites, 147 tests pass (+10 new). New tests cover order preservation, once-per-batch auth off events[0], per-event envelope fan-out, rethrow paths, and CDK template assertions for MaxBatchSize + BatchInvoke/lambdaResult templates plus the typedErrors guard.
  • npm run eslint: clean.

Notes

The S type parameter is bounded S extends Record<string, any> | null (the upstream default in @types/aws-lambda), because S = any does not compile against AppSyncBatchResolverHandler.

maxBatchSize is forwarded straight to the L2 and is not range-validated at synth time; AppSync caps it at 2000, so an out-of-range value fails at deploy.

Add the batched counterpart to createAppSyncHandler. It takes an array of
resolver events, authenticates once per batch off the first event, and returns
R[] in source order. The context carries both ctx.event (events[0]) and the
full ctx.events array.

Factor the typed-error normalisation and envelope construction out of
createAppSyncHandler into shared toTypedError/buildErrorEnvelope helpers so both
handlers use the identical error model. createAppSyncHandler behavior is
unchanged. With APPSYNC_TYPED_ERRORS=true the batch handler returns one error
envelope per event; otherwise it rethrows.
@hoegertn
hoegertn merged commit a83a1a5 into main Oct 20, 2026
4 checks passed
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.

AppSync: first-class Lambda BatchInvoke support (createAppSyncBatchHandler + maxBatchSize on addLambdaResolver)

2 participants