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

@yusufkaranib/queuecraft

v0.3.2

Published

Reliable TypeScript job processing for AWS SQS with DynamoDB idempotency and observability

Readme

QueueCraft

CI npm license

QueueCraft is a TypeScript toolkit for moving slow or failure-prone work out of web requests and into AWS SQS. It supplies the queue plumbing so an application can publish a job, process it with bounded concurrency, retry failures, and avoid repeating completed work.

QueueCraft is the reusable engine. It now has two different reference applications: YallaQueue for WhatsApp bookings and a business-neutral order-processing example. The second example proves that QueueCraft is not tied to one application.

Status

QueueCraft 0.3.2 is feature-complete for its portfolio scope and is maintained for documentation, dependency, security, and correctness fixes. Its unit-tested core and AWS infrastructure are usable for controlled pilots, but it has not yet earned a production-ready claim.

Evidence: 118 automated tests, enforced coverage floors, history-aware secret scanning, Node.js 20 and 22 CI, and recorded isolated real-AWS runs covering successful processing, duplicate suppression, failure, dead-letter redrive, trace propagation, and stack cleanup. The AWS test role was removed during the cost shutdown on 3 October 2026, so real-AWS testing is currently manual and unavailable until that isolated role is restored. See the verification record.

Implemented:

  • SQS publisher with caller-controlled idempotency keys
  • Long-polling worker with bounded concurrency
  • SQS-triggered Lambda batch processor with partial-message retries
  • DynamoDB execution leases and completed-job duplicate suppression
  • SQS visibility and DynamoDB lease heartbeats for long jobs
  • Bounded graceful shutdown with handler cancellation
  • CloudFormation for a standard queue, DLQ, DynamoDB table, IAM policies, alarms, and an optional private operations dashboard
  • Guarded integration runner verified against real SQS and DynamoDB
  • Guarded isolated AWS integration workflow using short-lived GitHub OIDC credentials when enabled
  • Structured, payload-free lifecycle events for logs and metrics
  • Buffered CloudWatch application metrics with bounded dimensions
  • OpenTelemetry-compatible lifecycle tracing without payload attributes
  • Active handler tracing so instrumented database and API calls can become child spans
  • Opt-in W3C traceparent/tracestate continuation from publishers through SQS to workers
  • Loopback-only queue dashboard with body-hidden DLQ metadata and guarded replay
  • Automated checks for Node.js 20 and 22
  • Pinned Gitleaks scanning with full Git history available in CI
  • Public npm package: @yusufkaranib/queuecraft

Deliberate limit:

  • Messaging span links for batch processing and manual DLQ replay

Try the demo in two minutes

Requirements: Git, Node.js 20 or 22, and npm. AWS credentials are not needed.

git clone https://github.com/Yusuf-Karanib/QueueCraft.git
cd QueueCraft
npm ci
npm run dashboard:demo

Open the local address printed in the terminal. The demo uses fake queue data, stays on 127.0.0.1, and cannot change AWS resources. It shows queue health, safe dead-letter metadata with message bodies hidden, and guarded replay.

QueueCraft local dashboard using fake data

For the historical real-cloud evidence, open the passing AWS integration run. That run created an isolated SQS queue, DLQ, and DynamoDB table, exercised the order example, and deleted the complete stack.

Why SQS?

A webhook should respond quickly. It should not keep the sender waiting while the application calls other services, writes several records, or sends a message. QueueCraft separates those two jobs:

webhook or API -> QueueCraft publisher -> SQS -> QueueCraft worker -> business logic
                                              |
                                              +-> DLQ after repeated failures

SQS standard queues provide at-least-once delivery. That means the same logical job can arrive more than once. QueueCraft records execution state in DynamoDB to reduce duplicate execution, but it cannot promise universal exactly-once side effects. Handlers must still be safe to retry.

SQS redrive policy—not QueueCraft application code—moves repeatedly failing messages to the DLQ.

Architecture

flowchart LR
  A[Webhook, API, or application] --> B[QueueCraft publisher]
  B -->|job plus W3C trace context| C[Amazon SQS]
  C --> D[QueueCraft poller or Lambda processor]
  D --> E[Application business handler]
  D <--> F[DynamoDB leases and completed jobs]
  C -->|repeated failure| G[Dead-letter queue]
  D --> H[CloudWatch events, metrics, alarms, and dashboard]

QueueCraft owns the reusable queue behavior. Each application still owns its payload rules and business action. DynamoDB reduces duplicate execution, while SQS remains an at-least-once system; the business handler must still be safe to retry.

Install

npm install @yusufkaranib/queuecraft

Version 0.3.2 is the current public alpha. Pin the version for controlled pilots and review the changelog before upgrading.

Publishing a job

Use a stable identifier from the source event. For a WhatsApp webhook, use the Meta message ID instead of generating a new value on every retry.

import { SQSClient } from "@aws-sdk/client-sqs";
import { QueueCraftPublisher } from "@yusufkaranib/queuecraft";

const publisher = new QueueCraftPublisher({
  sqsClient: new SQSClient({ region: process.env.AWS_REGION }),
  queueUrl: process.env.QUEUE_URL!,
});

await publisher.publish(
  {
    type: "booking_request",
    phoneNumber: "971500000000",
    requestedTime: "2026-09-01T15:00:00+04:00",
  },
  { idempotencyKey: whatsappMessageId },
);

When no idempotency key is supplied, QueueCraft generates a UUID. That is only appropriate when the publish operation will never be retried as the same job.

Processing jobs

import { DynamoDBClient } from "@aws-sdk/client-dynamodb";
import { SQSClient } from "@aws-sdk/client-sqs";
import {
  IdempotencyStore,
  QueueCraftPoller,
  Semaphore,
} from "@yusufkaranib/queuecraft";

const concurrency = 5;
const poller = new QueueCraftPoller({
  sqsClient: new SQSClient({ region: process.env.AWS_REGION }),
  queueUrl: process.env.QUEUE_URL!,
  semaphore: new Semaphore(concurrency),
  idempotency: new IdempotencyStore({
    client: new DynamoDBClient({ region: process.env.AWS_REGION }),
    tableName: process.env.IDEMPOTENCY_TABLE!,
  }),
  worker: {
    concurrency,
    pollIntervalMs: 250,
    shutdownTimeoutMs: 30_000,
  },
  handler: async (message, context) => {
    if (context.signal.aborted) return;
    const job = JSON.parse(message.Body ?? "null");
    await processJob(job, context.signal);
  },
  onError: (error) => console.error(error),
  onEvent: (event) => {
    const safeEvent = "idempotencyKey" in event
      ? { ...event, idempotencyKey: "[redacted]" }
      : event;
    console.log(JSON.stringify(safeEvent));
  },
});

await poller.start();

Call await poller.stop() during application shutdown. QueueCraft first lets active handlers finish. When shutdownTimeoutMs expires, their AbortSignals are cancelled and the worker stops extending message visibility. A handler that ignores its signal may keep running in application code, but stop() will not wait forever and the DynamoDB lease can eventually expire.

The poller heartbeat must be shorter than both its SQS visibility timeout and the IdempotencyStore lease. The default is half of the shorter deadline. QueueCraft rejects a configuration that could let either lease expire before a heartbeat.

For an SQS-triggered Lambda, configure the event-source mapping with ReportBatchItemFailures. QueueCraftLambdaProcessor returns per-record failures; without that Lambda setting, AWS ignores the partial response and can acknowledge failed records. The Lambda processor's DynamoDB heartbeat must also be strictly shorter than the idempotency lease; it defaults to half that lease. If renewal fails, QueueCraft cancels the handler signal and returns that record as failed without trying to settle work under uncertain ownership.

CloudWatch metrics and tracing

QueueCraft can turn the same payload-free lifecycle events into CloudWatch metrics and OpenTelemetry-compatible spans:

Since version 0.3.0, QueueCraft includes QueueCraftActiveTracing, W3C trace propagation, and the optional AWS operations dashboard.

For the optional OpenTelemetry example, install its API in the application:

npm install @opentelemetry/api

Also configure an OpenTelemetry SDK, asynchronous context manager, and W3C propagator. The API package by itself is a no-op.

import { CloudWatchClient } from "@aws-sdk/client-cloudwatch";
import {
  QueueCraftActiveTracing,
  QueueCraftCloudWatchMetrics,
  QueueCraftTracingObserver,
  QueueCraftW3CTraceContext,
} from "@yusufkaranib/queuecraft";
import { context, propagation, ROOT_CONTEXT } from "@opentelemetry/api";

const metrics = new QueueCraftCloudWatchMetrics({
  client: new CloudWatchClient({ region: process.env.AWS_REGION }),
  namespace: "queuecraft/dev",
  dimensions: { Service: "booking-worker" },
});
const tracing = new QueueCraftTracingObserver({ tracer });
const activeTracing = new QueueCraftActiveTracing({ tracer });
const traceContext = new QueueCraftW3CTraceContext({
  context,
  propagation,
  rootContext: ROOT_CONTEXT,
});

const onEvent = (event) => {
  metrics.onEvent(event);
  tracing.onEvent(event);
};

Pass onEvent to either the poller or Lambda processor. During shutdown, call await metrics.close() and tracing.close(). Full setup and privacy limits are in docs/observability.md.

Pass activeTracing as the processor's instrumentation option. It makes work started by the business handler part of the active trace context. Pass the same traceContext to QueueCraftPublisher and to the poller or Lambda processor to continue a producer's W3C parent through SQS. The application must configure its OpenTelemetry SDK, context manager, and W3C propagator; the API alone is a no-op. QueueCraft carries only traceparent and tracestate, never baggage.

DynamoDB table requirement

The idempotency table uses a String partition key named messageId. DynamoDB TTL should be enabled on the Number attribute expiresAt. Correctness does not depend on immediate TTL deletion; lease takeover checks leaseUntil directly.

Run the repository locally

To work on QueueCraft itself, use Node.js 20 or 22 and run:

npm ci
npm test
npm run test:coverage
npm run typecheck
npm run build

The coverage command measures every TypeScript source file, including files a test never loads. CI requires at least 85% statements, 75% branches, 85% functions, and 85% lines. The unit tests mock AWS, so passing them does not replace the guarded real-AWS integration test.

A guarded real-AWS test runner is included in docs/aws-integration-test.md. It must be run against a dedicated test stack; it deliberately refuses to use a non-empty queue. Its passing AWS runs are recorded in docs/verification.md. The workflow is manual while the AWS test role remains deleted. After that isolated role is deliberately restored, a maintainer must confirm the temporary resource cost before a run can create the test stack. The project remains alpha until it has evidence from controlled pilots.

Deploy the AWS resources

The template and beginner deployment instructions are in infrastructure/. The template creates a standard queue, DLQ, DynamoDB lease table, separate least-privilege publisher and worker policies, and CloudWatch alarms. It accepts only dev and test; it is not a production baseline. Production planning starts with the AWS operations checklist, not by relabelling this stack. The operations dashboard and sustained backlog alarm are opt-in so deploying the default template does not silently add those two resources or their possible CloudWatch charges.

See docs/observability.md for safe event logging and suggested metrics. See docs/yallaqueue-reference.md for the first end-to-end application built on QueueCraft. The independent examples/order-processing application is the second reference and was exercised by the recorded guarded real-AWS runs.

For a short case study, resume bullet, and recording script, see docs/portfolio.md.

The maintained capstone evidence is split into the baseline audit, requirements, threat model, verification record, and agent-workflow evaluation protocol. The completed agent-workflow comparison records what was tested, what was adopted, and why no workflow package was installed globally.

Local dashboard

The dashboard shows ready, in-flight, and dead-letter counts. It can replay a failed standard-queue job only after a confirmation. It binds to your computer, keeps AWS credentials on the server, and hides message bodies by default.

See docs/dashboard.md for setup and safety limits. Release steps are documented in docs/releasing.md.

Maintenance scope

There is no active feature roadmap. New production-facing behavior should be added only when a controlled pilot supplies a clear requirement and a way to verify it. The current maintenance focus is keeping tests, dependencies, documentation, and security guidance accurate.

License

MIT