Skip to main content
Amazon SQS is an alternative queue provider: fully managed by AWS, no Redis required, and emulated locally via Localstack.

Why

SQS is the right choice when you want a fully managed, serverless queue with no Redis dependency in production. It scales automatically, integrates natively with the rest of your AWS infrastructure, and removes the operational burden of managing a Redis cluster. Locally it runs through Localstack, so the dev loop stays self-contained inside Docker.

Setup

  1. In apps/backend/package.json, add "tooling-queue-sqs": "workspace:*" under dependencies and remove any other queue adapter package.
  2. Run make deps-install.
  3. In development.ts, production.ts, and test.ts, set tools.queue:
  4. In compose.yml, add Localstack and optionally SQS Admin, and wire backend and consumer to start after Localstack is healthy. Add an init container that creates your queues before the backend starts:
  5. In .env.development, uncomment and set the SQS vars — placeholder values work for Localstack:
  6. Run make test module=tooling-queue-sqs and make test module=backend.

Local observability

Localstack exposes its health and queue state at http://localhost:4566/_localstack/health. For a full queue UI locally, add the sqs-admin service to compose.yml (port 3999) pointed at http://localstack:4566.
Bull Board (port 3998) does not show SQS traffic — it reads Redis only. If Bull Board is still in your Compose file from a previous BullMQ setup, it will appear empty and can be removed.

Adding a new queue

  1. Add the queue name and its DLQ to the QueueName enum in apps/backend/src/utilities/queue.ts.
  2. Add a matching config block under tools.queue.queues in each env config file — copy an existing entry and adjust the name and retry settings.
  3. Add the awslocal sqs create-queue call for both the queue and DLQ to your sqs-init container in compose.yml — SQS does not auto-create queues.
  4. Add the consumer to apps/backend/src/tools/queue/consumerRegistry.ts. Skip this if you only need a producer.
  5. Run make test module=backend.

Gotchas

  • SQS queues must be created before the consumer starts. If sqs-init hasn’t run yet, the consumer will fail silently on startup.
  • Deferred enqueue (delayMs / runAt with jobId), replace: true, and removeQueuedJob need tools.cache.client (Redis) on API and consumer. SQS cannot delete in-flight messages by id — the adapter tracks generations in Redis and skips stale or cancelled messages when consuming.
  • sendToQueue delay is capped at 900 seconds. Longer schedules (e.g. blog publish) rely on DB state plus scheduler reconcile, same as BullMQ.
  • Never commit real AWS credentials in .env.development — the placeholder values (test / test) are intentional for Localstack and safe to commit.
  • SQS_ENDPOINT must be omitted (or left unset) in production config. Pointing it at Localstack in production will silently swallow all messages.
  • Never add @aws-sdk/client-sqs directly to apps/backend/package.json — it is a transitive dependency of tooling-queue-sqs and should stay that way.

What’s next?

  • BullMQ — default Redis-backed provider with Bull Board.
  • Configuration — switching pluggable tool implementations.
  • Tooling system — how loaders and workspace packages fit together.