Local AWS Emulators for JavaScript Teams: When to Use kumo vs. LocalStack
cloudtestingnodejs

Local AWS Emulators for JavaScript Teams: When to Use kumo vs. LocalStack

AAlex Mercer
2026-04-08
7 min read
Advertisement

A practical comparison to help JS engineers choose kumo or LocalStack for local AWS emulation in CI and dev—performance, coverage, persistence, and Node.js examples.

Local AWS Emulators for JavaScript Teams: When to Use kumo vs. LocalStack

Short verdict: use kumo when you need a tiny, fast emulator for CI and local dev with simple persistence and low overhead; use LocalStack when you need the widest feature coverage, production-like behavior, or integrations that depend on more accurate AWS APIs. Below you'll find concrete tradeoffs, Node.js examples (S3 + DynamoDB), and actionable recommendations for CI/CD testing and local development.

Why local AWS emulation matters for JavaScript teams

Developers building Node.js services that talk to AWS (S3, DynamoDB, SQS, Lambda, etc.) need reliable tests and fast local feedback. Real AWS services are great for integration tests but slow, costly, and brittle for inner-loop development or ephemeral CI jobs. Local AWS emulators let you:

  • Run end-to-end tests in CI without network dependency or AWS bills.
  • Iterate locally with fast startup and repeatable state.
  • Simulate failure modes and edge cases offline.

Both projects emulate AWS APIs but target different tradeoffs:

  • kumo: a lightweight AWS service emulator (single binary, no auth, Docker support). Great for CI and local dev where startup time and resource usage matter. It advertises optional data persistence and supports many services.
  • LocalStack: a feature-rich emulator ecosystem (OSS + Pro tiers). It aims to be API-compatible with more AWS behaviors, supports a broad set of services and integrations, and offers commercial add-ons for parity-critical testing.

Key tradeoffs: performance, coverage, persistence, and SDK compatibility

1) Performance and resource usage

kumo is designed to be lightweight. It starts fast, consumes less CPU/memory, and is easier to ship as a single binary inside ephemeral CI jobs or test containers. Use kumo when your CI pipeline needs to spin up an emulator per test job and you care about flakiness introduced by resource contention.

LocalStack can be heavier: it spins up many service mocks and in some setups launches additional containers (e.g., for edge services). For small teams or constrained CI runners, LocalStack may increase test times and resource usage unless you restrict the services you start.

2) Feature coverage and fidelity

LocalStack typically offers higher fidelity for complex AWS APIs (IAM behaviors, nuanced S3 semantics, Lambda integrations, EventBridge rules, etc.). If your test suite exercises advanced AWS features or expects near-production behavior, LocalStack is often the safer choice.

kumo supports a surprisingly wide range of services (many core services are implemented), but some edge behaviors or advanced APIs might be missing or simplified. If your app relies on subtle API semantics, validate against kumo early.

3) Persistence and state management

kumo advertises optional data persistence (a data directory to survive restarts). That makes it convenient for local dev where you want to preserve test fixtures between runs without re-initializing data from fixtures on every start.

LocalStack also supports persistent volumes (via Docker) and can persist state for certain services, but some teams prefer fresh state per test run to avoid cross-test contamination. Both tools allow you to choose either approach.

4) SDK compatibility (Node.js specifics)

Both emulators expose HTTP endpoints that the AWS SDKs can target. Node.js apps using the AWS SDK v2 or v3 can connect to either emulator by configuring the service client endpoint and credentials. LocalStack has a long track record with Node.js SDKs; kumo is newer and optimized for lightweight setups—be sure to run a quick compatibility smoke test for any SDK version you use.

Concrete Node.js examples (S3 + DynamoDB)

The examples below use environment variables for the emulator endpoint so you can plug-in LocalStack or kumo without editing code.

Common notes

  • Set EMULATOR_ENDPOINT to your emulator root (e.g. http://localhost:4566 for LocalStack, or http://localhost:PORT for kumo depending on your configuration).
  • Both emulators typically do not require real AWS credentials. You can set dummy credentials to satisfy the SDK.

S3 (Node.js AWS SDK v3)

const { S3Client, PutObjectCommand, GetObjectCommand } = require("@aws-sdk/client-s3");

const endpoint = process.env.EMULATOR_ENDPOINT; // e.g. http://localhost:4566
const s3 = new S3Client({
  endpoint,
  region: "us-east-1",
  credentials: { accessKeyId: "test", secretAccessKey: "test" },
  forcePathStyle: true // useful for many emulators
});

async function putAndGet() {
  await s3.send(new PutObjectCommand({ Bucket: "my-bucket", Key: "test.txt", Body: "hello" }));
  const resp = await s3.send(new GetObjectCommand({ Bucket: "my-bucket", Key: "test.txt" }));
  const body = await streamToString(resp.Body);
  console.log(body);
}

function streamToString(stream) {
  return new Promise((resolve, reject) => {
    const chunks = [];
    stream.on("data", (c) => chunks.push(c));
    stream.on("error", reject);
    stream.on("end", () => resolve(Buffer.concat(chunks).toString("utf8")));
  });
}

putAndGet().catch(console.error);

DynamoDB (Node.js AWS SDK v3)

const { DynamoDBClient, PutItemCommand, GetItemCommand } = require("@aws-sdk/client-dynamodb");

const endpoint = process.env.EMULATOR_ENDPOINT; // e.g. http://localhost:4566
const ddb = new DynamoDBClient({
  endpoint,
  region: "us-east-1",
  credentials: { accessKeyId: "test", secretAccessKey: "test" }
});

async function putAndGetItem() {
  await ddb.send(new PutItemCommand({
    TableName: "users",
    Item: { id: { S: "user-1" }, name: { S: "Alice" } }
  }));

  const resp = await ddb.send(new GetItemCommand({ TableName: "users", Key: { id: { S: "user-1" } } }));
  console.log(JSON.stringify(resp.Item));
}

putAndGetItem().catch(console.error);

How to run the emulators (practical commands)

General pattern: set an endpoint env var, run the emulator in a container or as a binary, and point Node.js tests to that endpoint.

  1. Start LocalStack (simplest):
    docker run --rm -p 4566:4566 -p 4571:4571 localstack/localstack
    Then set EMULATOR_ENDPOINT=http://localhost:4566
  2. Start kumo (binary or Docker):

    kumo is distributed as a single binary and has Docker support. Example (replace <port> with a port you expose):

    docker run --rm -p <port>:<port> sivchari/kumo:latest
    # then set EMULATOR_ENDPOINT=http://localhost:<port>

    Check the kumo repo for exact flags (data dir, service toggles, etc.).

CI/CD testing patterns

Pick emulators according to CI constraints and test intent:

  • Fast unit tests / short-lived CI jobs: spin up kumo per job (fast start, low RAM). Use ephemeral state and avoid persistent volumes.
  • Integration tests that mimic production: use LocalStack with service selection to reduce resource use (start only the services you need). Consider LocalStack Pro if specific AWS behaviors are required.
  • Parallel CI runners: prefer light emulators or a shared mocked endpoint managed by a single long-lived service to avoid bootstrapping costs.

Troubleshooting & practical tips

  • Always set forcePathStyle for S3 in Node.js clients. Many emulators use path-style buckets (not virtual-hosted style).
  • Use dummy credentials when the emulator doesn't enforce IAM; this keeps code compatible with real AWS flows.
  • Keep a smoke test that runs on every PR to detect emulator/API drift early.
  • If an emulator behaves differently from AWS, write contract tests against real AWS for a small number of nightly/integration runs.

Choosing based on use-case

  • Choose kumo if you want: minimal resource footprint, fast startup, simple persistence, and easy distribution (single binary). Ideal for lightweight CI jobs and local dev where near-perfect AWS fidelity isn’t required.
  • Choose LocalStack if you want: wide API coverage, closer-to-AWS behavior for complex services, and an ecosystem of helpers/CI integrations. Ideal for teams that need production parity in tests or use advanced AWS features.

Local emulators are just one part of a resilient developer workflow. For more on how developer tools and workflows are evolving, see our piece on Understanding AI's Impact on Developer Workflows. If you build systems that need graceful service fallbacks during outages, this approach pairs well with emulator-driven tests — see Create a Minimal LLM Fallback Component for patterns you can adapt.

Summary

Both kumo and LocalStack are useful tools for JavaScript teams. Pick kumo for speed, low overhead, and simplicity. Pick LocalStack for fidelity, larger coverage, and production-alike tests. In practice, many teams use both: kumo for quick CI and local dev tasks, LocalStack for deeper integration tests. Always validate critical behaviors against real AWS regularly and keep your emulator-based tests focused on fast feedback during development.

Advertisement

Related Topics

#cloud#testing#nodejs
A

Alex Mercer

Senior SEO Editor

Senior editor and content strategist. Writing about technology, design, and the future of digital media. Follow along for deep dives into the industry's moving parts.

Advertisement
2026-04-17T02:43:23.230Z