sqs-partial-batch-processor
v0.4.3
Published
A small TypeScript helper for AWS Lambda SQS triggers using partial batch responses (SQSBatchResponse.batchItemFailures). You supply per-record async logic; the library handles looping, per-record error boundaries, and the response shape.
Readme
SQS Partial Batch Processor
A small TypeScript helper for AWS Lambda SQS triggers using partial batch responses (SQSBatchResponse.batchItemFailures).
You supply per-record async logic; the library handles looping, per-record error boundaries, and the response shape.
This library intentionally does not parse message bodies, validate schemas, create AWS SDK clients, or make retry/business decisions for you.
Import the public API from the package root (processPartialBatch, processPartialBatchWithResult, ProcessPartialBatchOptions, ProcessRecordResult).
Features
- Implements Lambda SQS partial batch response pattern (only failed messages are retried).
- Per-record error boundary (failures are isolated to each record).
- Aggregates failed identifiers into
batchItemFailures(defaults tomessageId). - Throw-style (
processPartialBatch) and Result-style (processPartialBatchWithResult) APIs. - Typed Result callback via
ProcessRecordResult({ ok: true }|{ ok: false }). - Optional bounded concurrency (
concurrency), error hook (onRecordError), and customitemIdentifiermapping (mapMessageId). - Shared options type
ProcessPartialBatchOptionsfor both APIs. - For
{ ok: false },onRecordErrorreceives anErrorthat includes the resolveditemIdentifier(message andcause) for easier debugging.
Requirements
- Node.js 20+ (runtime requirement)
- Module system: published as CommonJS (
"main": "lib/index.js"). Usable from both CJS and ESM runtimes. - Lambda SQS event source mapping has Report batch item failures enabled. See: AWS Lambda SQS error handling docs
Installation
npm install sqs-partial-batch-processoryarn add sqs-partial-batch-processorpnpm add sqs-partial-batch-processorUsage
Throw to mark a record as failed:
import type { SQSEvent } from 'aws-lambda';
import { processPartialBatch } from 'sqs-partial-batch-processor';
export const handler = async (event: SQSEvent) =>
processPartialBatch(event, async (record) => {
// Your per-record logic here.
// Throw to mark only this record's messageId as failed.
});Result-style callback (no throw for control flow). Return a ProcessRecordResult:
{ ok: true }: success (not listed inbatchItemFailures){ ok: false }: failure (listed inbatchItemFailures)- thrown errors: still treated as failures
import type { SQSEvent } from 'aws-lambda';
import {
processPartialBatchWithResult,
type ProcessRecordResult,
} from 'sqs-partial-batch-processor';
export const handler = async (event: SQSEvent) =>
processPartialBatchWithResult(event, async (record): Promise<ProcessRecordResult> => {
if (record.body === '') {
return { ok: false };
}
return { ok: true };
});Options
Both processPartialBatch and processPartialBatchWithResult accept an optional ProcessPartialBatchOptions object:
concurrency?: number(default:1): maximum parallelism. Must be a finite integer>= 1(1= sequential,> 1= bounded concurrency). If invalid, the function throws (RangeErrorfor< 1,TypeErrorfor non-integer / non-finite).- Tip: start with
1and increase gradually while watching downstream limits (external API rate limits, DB connection pools, and Lambda reserved concurrency). SQS batches are typically small, so a large value rarely helps. - Note: when
concurrency > 1, the order ofbatchItemFailuresis not guaranteed. Tests should compare as a set, not by array order.
- Tip: start with
onRecordError?: (record, error) => void: called when a record is treated as failed (useful for structured logs / metrics).- Caution: do not log
record.bodyas-is inonRecordError. Message bodies often contain secrets or personal data. PrefermessageId/ yourmapMessageIdresult and a sanitized error summary. - When
processPartialBatchWithResultreceives{ ok: false }, the hook gets anErrorwhose message (andcause.itemIdentifier) includes the resolveditemIdentifierfor easier debugging. - Example (structured log / metrics hook):
- Caution: do not log
import type { SQSEvent } from 'aws-lambda';
import { processPartialBatch } from 'sqs-partial-batch-processor';
export const handler = async (event: SQSEvent) =>
processPartialBatch(
event,
async (record) => {
// ...
},
{
onRecordError: (record, error) => {
console.log(JSON.stringify({
level: 'error',
msg: 'record failed',
messageId: record.messageId,
// Do not log record.body — it may contain secrets or PII.
error: error instanceof Error ? { name: error.name, message: error.message } : { message: String(error) },
}));
},
},
);mapMessageId?: (record) => string: customize theitemIdentifier(defaults torecord.messageId).- Typical uses: align the identifier with an application-level id (e.g., an id stored in
messageAttributesor the parsed payload), or normalize identifiers across FIFO/standard queues for easier correlation.
- Typical uses: align the identifier with an application-level id (e.g., an id stored in
License
This project is licensed under the Apache-2.0 License.
