# sivchari/kumo: a single-binary AWS emulator for CI and local development

> kumo is a Go AWS service emulator that runs as one binary or container on port 4566, with 82 services listed and optional persistence through KUMO_DATA_DIR. It fits Go teams that want AWS SDK v2 calls to hit a local endpoint in tests.

**sivchari/kumo** — A lightweight AWS service emulator written in Go. Works as both a CI/CD testing tool and a local development server with optional data persistence.

- Repository: https://github.com/sivchari/kumo
- Stars: 1,488 · Forks: 93
- Language: Go
- License: MIT
- Published: 2026-08-08 · Updated: 2026-08-18 · Language: en
- Canonical page: https://hysenlabs.com/projects/sivchari-kumo

## The problem kumo targets: AWS calls in tests without an AWS account

Integration tests that create an S3 bucket, send an SQS message or write a DynamoDB item normally need credentials, a region and a real account. That makes tests slow, costs money, and turns a CI job into something that depends on an external service being reachable. kumo takes the other route: it speaks the AWS wire protocol locally, so the same SDK code runs against http://localhost:4566 instead of amazonaws.com.

The README frames it as "a lightweight AWS service emulator written in Go" that "works as both a CI/CD testing tool and a local development server with optional data persistence." The intended reader is a Go developer whose code already imports github.com/aws/aws-sdk-go-v2. The README states the emulator is "AWS SDK v2 compatible" and requires no authentication, which removes the credential setup that usually sits in front of a test fixture. If your stack is Python boto3 or the AWS CLI, nothing in the repository says kumo is aimed at you, though the SDKs share an endpoint model.

## One process, port 4566, and a service catalog generated from code

kumo ships as a single Go binary. The Makefile builds it with go build -ldflags "-X main.version=$(VERSION)" -o bin/kumo ./cmd/kumo, and the version string is read from version.go. Everything runs in that one process; there is no database or sidecar required to start it.

The README lists 82 services, grouped into categories such as Storage, Compute, Container, Database, Messaging, Security, Monitoring, Networking, Analytics and Developer Tools. That table is not maintained by hand. The README carries a generator marker: the catalog is "auto-generated from each service's Meta(); run make readme to update. Do not edit by hand." The Makefile confirms this with a readme target that runs go run ./cmd/readme-gen. Each service registers its own metadata, and the docs are derived from it, which is a reasonable way to keep a long list from drifting.

Two configuration paths are visible. The docker-compose.yml in the repository sets KUMO_HOST=0.0.0.0, KUMO_PORT=4566 and KUMO_LOG_LEVEL=debug, and defines a healthcheck that runs wget -q --spider http://localhost:4566/health every 5 seconds with 3 retries. That health endpoint is the one thing a CI pipeline can poll before running tests. Persistence is opt-in through KUMO_DATA_DIR; without it, state lives in memory and disappears when the process stops.

## Installing kumo and pointing an AWS SDK v2 client at it

The fastest path is the published container image. The README gives this command, which maps the emulator's port to the host:

```bash
docker run -p 4566:4566 ghcr.io/sivchari/kumo:latest
```

If you want state to survive a restart, the README adds a data directory and a named volume:

```bash
docker run -p 4566:4566 \
  -e KUMO_DATA_DIR=/data \
  -v kumo-data:/data \
  ghcr.io/sivchari/kumo:latest
```

Building from source uses the Makefile. The build target produces bin/kumo, and the run target skips the build step entirely:

```bash
make build
./bin/kumo
```

For a Compose-based workflow, the README's example declares the service on port 4566 and, in the persistence variant, sets KUMO_DATA_DIR=/data with a kumo-data volume. The repository's own docker-compose.yml builds from docker/Dockerfile instead of pulling the image and adds the debug log level.

On the client side, the README's S3 example loads a default config for us-east-1 with static credentials ("test", "test") and overrides the endpoint. The key detail is path-style addressing, which the example sets alongside the base endpoint:

```go
client := s3.NewFromConfig(cfg, func(o *s3.Options) {
    o.BaseEndpoint = aws.String("http://localhost:4566")
    o.UsePathStyle = true
})
```

Run that against a local kumo process and the SDK's calls land on your machine. The README also shows an SQS client built the same way, with only BaseEndpoint overridden, so the pattern generalizes across service clients.

## Where kumo is the wrong tool

The breadth of the service list is the thing to be skeptical about. A catalog of 82 services auto-generated from Meta() tells you what each service declares about itself, not how much of each API surface is implemented. The README does not publish a per-operation compatibility matrix. If your test exercises an obscure DynamoDB conditional expression, an S3 multipart edge case or a Step Functions state machine feature, you cannot tell from the README whether it will behave like the real service or return something else.

Behavioural fidelity is the second gap. An emulator is not AWS. IAM policy evaluation, eventual consistency, throttling responses, and service quotas are the kinds of things an emulator typically simplifies, and the README is silent on all of them. A test that passes against kumo is evidence that your code calls the API correctly, not that your permissions or limits are right in a real account. Teams that need to validate IAM policies or quota handling should keep a real-account test path.

There is also a language assumption. Every usage example in the README is Go, and the project depends on github.com/aws/aws-sdk-go-v2 modules. Other SDKs can point at an endpoint, but kumo's own testing and examples are Go-shaped, so users of other languages are working outside the demonstrated path.

## kumo compared with LocalStack

LocalStack is the reference point most teams already know, and the difference is architectural rather than cosmetic. LocalStack is a Python application distributed as a container, with a paid tier for advanced features. kumo is a Go program that compiles to a single binary, which is why the README can advertise "single binary" and "fast startup, minimal resource usage" as properties of the distribution model.

That matters in two places. In CI, a single static binary can be dropped into a job image without a container runtime or a Python environment. On a laptop, it starts as one process you can kill and restart without pulling an image. The trade-off runs the other way too: LocalStack has years of accumulated service coverage and community documentation, while kumo's README offers a generated service list and no compatibility depth. Choosing kumo means choosing the simpler artifact and accepting that you will verify coverage yourself.

The repository also carries charts/ and a Makefile target test-helm-e2e that runs test/e2e/helm-e2e.sh, which suggests a Kubernetes deployment path exists alongside Docker. The README's Quick Start does not document it, so treat Helm as something to inspect in the repository rather than a documented install route.

## Maintenance, licensing and the cost of upgrading

The last push to the default branch was on 2026-08-07, and the most recent release is v0.28.1 from the same day, following v0.28.0 and v0.27.0 in the weeks before. The repository is not archived. The version number is still below 1.0, so the project makes no compatibility promise across releases, and the release cadence visible in the tags is frequent enough that pinning a version is the sane default.

Upgrade cost is concentrated in two places. The first is the service catalog: since the README table is regenerated from each service's Meta(), a release can change what is listed without a corresponding note in the README. The second is the Go dependency graph. go.mod requires go 1.25.0 with toolchain go1.25.10 and pins aws-sdk-go-v2 modules such as v1.43.4, so building from source tracks a recent Go toolchain. If you consume the container image, that concern disappears.

The licence is MIT, which permits commercial use and modification with the copyright notice retained. That is a permissive licence, but it says nothing about the accuracy of the emulation, and the README makes no warranty claims either way. If your organisation requires a support contract or a vendor to escalate to, kumo does not offer one.

## Conclusion

kumo fits Go teams that already use AWS SDK v2 and want their integration tests to talk to a local endpoint instead of a real account. Teams that need faithful behaviour for every one of the 82 listed services, or that develop against non-Go SDKs and expect full API parity, should check per-service coverage before committing. Verify first whether the specific operations you call are implemented, whether you need KUMO_DATA_DIR for state across restarts, and whether the /health endpoint is what your CI waits on.

## FAQ

### What port does sivchari/kumo listen on?

The README and the repository's docker-compose.yml both use port 4566, and the Compose file sets KUMO_PORT=4566 alongside KUMO_HOST=0.0.0.0. The Docker examples map 4566:4566, so the emulator is reachable at http://localhost:4566.

### Does sivchari/kumo keep data after a restart?

Only when persistence is enabled. The README describes "optional data persistence" controlled by KUMO_DATA_DIR, and its Docker example mounts a volume at /data while setting that variable. Without it, the README does not describe any persistence mechanism.

### Does sivchari/kumo need AWS credentials?

The README lists "No authentication required" as a feature and calls this out as suitable for CI environments. Its Go examples still pass static credentials ("test", "test") to the SDK config, which is the usual way to satisfy the SDK's credential chain while talking to a local endpoint.

### How do I check that sivchari/kumo is running?

The repository's docker-compose.yml defines a healthcheck that runs wget -q --spider http://localhost:4566/health with a 5 second interval and 3 retries. That /health path is the readiness signal the project itself uses.

### What is the best AWS emulator?

The repository does not make a comparative claim, and the README presents kumo on its own terms: a single Go binary, no authentication, 82 listed services, and optional persistence via KUMO_DATA_DIR. LocalStack is the better-known alternative, and the real difference is that kumo is a compiled Go binary while LocalStack is a Python application distributed as a container.

## Sources

- [Official README](https://github.com/sivchari/kumo#readme)
- [Project repository](https://github.com/sivchari/kumo)
- [Release notes](https://github.com/sivchari/kumo/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/sivchari-kumo
