npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

local-sqs-trigger

v1.0.2

Published

Trigger AWS Lambda SQS handlers locally for development and testing. Simulate SQS events using LocalStack and let your handler code runs unchanged and deploys to AWS as-is.

Readme

local-sqs-trigger

npm library to simulate AWS Lambda SQS triggers locally using LocalStack. Your handler code runs locally unchanged and deploys to AWS as-is.

npm

The problem

When you write a Lambda function triggered by SQS, the handler looks like this:

export const handler: SQSHandler = async (event) => {
  for (const record of event.Records) {
    await processOrder(JSON.parse(record.body))
  }
}

AWS manages the polling, batching, and message lifecycle for you. But locally, there is no equivalent. To test this code without deploying, you either write your own polling loop that you don't need in production — mixing dev scaffolding into your application code — or you deploy every change to AWS to test it, which is slow and expensive.

The solution

local-sqs-trigger is a thin runner that sits outside your application code. You write a single config file that maps queues to handler files, and the runner handles the polling, batching, visibility timeout, and message lifecycle — exactly as Lambda does in production.

Your handler code stays clean. No polling logic, no dev-only code paths. The same file deploys to Lambda unchanged.

Features

  • Same event shape as real Lambda — your handler receives the exact same SQSEvent it would get in AWS, no changes needed when you deploy
  • Partial batch failure — return SQSBatchResponse to fail individual messages while succeeding others
  • TypeScript-first — full type exports, .ts handler files supported at runtime via tsx
  • Config-driven — one file maps every queue to its handler
  • FIFO queue supportMessageGroupId and deduplication attributes preserved
  • Graceful shutdownSIGINT/SIGTERM waits for the current batch to finish
  • Works against real AWS too — omit endpoint to point at real SQS

Requirements

Installation

npm install local-sqs-trigger

Quick Start

1. Start LocalStack

Docker (typical for local dev):

docker run --rm -p 4566:4566 -e SERVICES=sqs localstack/localstack

Docker Compose in your own repo (optional): create a docker-compose.yml next to your app and run docker compose up -d. Example:

services:
  localstack:
    image: localstack/localstack:latest
    ports:
      - "4566:4566"
    environment:
      - SERVICES=sqs

Use http://localhost:4566 as endpoint in the config below. If you use another host or port, adjust accordingly.

2. Create a config file

// sqs-triggers.config.ts
import { defineConfig } from 'local-sqs-trigger'

export default defineConfig({
  endpoint: 'http://localhost:4566',
  region: 'us-east-1',
  credentials: { accessKeyId: 'test', secretAccessKey: 'test' },
  queues: [
    {
      name: 'order-processing-queue',
      handler: './handlers/orderHandler',
      batchSize: 10,
      createIfNotExists: true,
    },
  ],
})

3. Write a handler

// handlers/orderHandler.ts
import type { SQSHandler } from 'local-sqs-trigger'

export const handler: SQSHandler = async (event) => {
  for (const record of event.Records) {
    const order = JSON.parse(record.body)
    console.log('Processing order:', order.id)
  }
}

4. Start the trigger

npx local-sqs-trigger start
# or specify a custom config path
npx local-sqs-trigger start --config ./config/sqs.config.ts

Config Reference

interface TriggerConfig {
  /** LocalStack or custom SQS endpoint. Omit for real AWS. */
  endpoint?: string

  /** AWS region. Default: 'us-east-1' */
  region?: string

  /** AWS credentials. Defaults to the standard credential chain. */
  credentials?: {
    accessKeyId: string
    secretAccessKey: string
    sessionToken?: string
  }

  /** One entry per queue. */
  queues: QueueConfig[]

  /** Log verbosity. Default: 'info' */
  logLevel?: 'debug' | 'info' | 'warn' | 'error' | 'silent'
}

interface QueueConfig {
  /** SQS queue name (not a URL or ARN). */
  name: string

  /**
   * Path to the handler file, relative to the config file.
   * Supports .ts, .js, .mjs extensions. No extension required.
   */
  handler: string

  /** Messages per poll (1–10). Default: 10 */
  batchSize?: number

  /** Visibility timeout in seconds while the handler runs. */
  visibilityTimeout?: number

  /**
   * Auto-create the queue if it doesn't exist.
   * Intended for local dev only. Default: false (matches AWS behaviour).
   */
  createIfNotExists?: boolean

  /** Extra queue attributes passed to CreateQueue (when createIfNotExists is true). */
  queueAttributes?: Record<string, string>
}

Handler Signature

Handlers match the real AWS Lambda SQS handler contract exactly:

import type { SQSHandler, SQSEvent, SQSBatchResponse } from 'local-sqs-trigger'

// Simple handler — all messages succeed or all fail together
export const handler: SQSHandler = async (event: SQSEvent) => {
  for (const record of event.Records) {
    await processMessage(JSON.parse(record.body))
  }
}

// Partial batch failure — fail individual messages independently
export const handler: SQSHandler = async (event): Promise<SQSBatchResponse> => {
  const failures: string[] = []

  for (const record of event.Records) {
    try {
      await processMessage(JSON.parse(record.body))
    } catch {
      failures.push(record.messageId)
    }
  }

  return { batchItemFailures: failures.map((id) => ({ itemIdentifier: id })) }
}

When a handler throws, all messages in the batch are released back to the queue immediately (visibility timeout set to 0), matching real Lambda behaviour.

When a handler returns an SQSBatchResponse, only the failed message IDs are released; the rest are deleted.

Programmatic API

import { startTriggers, defineConfig } from 'local-sqs-trigger'

const instance = await startTriggers(defineConfig({
  endpoint: 'http://localhost:4566',
  queues: [{ name: 'my-queue', handler: './handler' }],
}))

// Graceful shutdown
process.once('SIGINT', () => instance.stop())
await instance.stopped

FIFO Queues

Use a queue name ending in .fifo. The MessageGroupId and MessageDeduplicationId are preserved in the SQSRecord attributes, matching the real Lambda event shape.

export default defineConfig({
  queues: [
    {
      name: 'orders.fifo',
      handler: './handlers/orders',
      createIfNotExists: true,
      queueAttributes: {
        FifoQueue: 'true',
        ContentBasedDeduplication: 'true',
      },
    },
  ],
})

Config File Discovery

The CLI searches for config files in this order:

  1. sqs-triggers.config.ts
  2. sqs-triggers.config.js
  3. sqs-triggers.config.mjs
  4. sqs-triggers.config.cjs
  5. sqs-triggers.config.json

Pass --config <path> to use a different location.

Contributing

To work on the library itself, clone the GitHub repository. It includes a docker-compose.yml for LocalStack used in development and CI-style integration tests.

git clone https://github.com/BhanukaRC/local-sqs-trigger.git
cd local-sqs-trigger
npm install
npm test
docker compose up -d   # LocalStack on :4566
npm run test:integration

License

MIT