Local AWS Emulation with KUMO: A Practical CI/CD Playbook for Developers
DevOpsTestingCloud

Local AWS Emulation with KUMO: A Practical CI/CD Playbook for Developers

UUnknown
2026-04-08
7 min read
Advertisement

Production-grade CI/CD patterns using KUMO: containerized runners, test isolation, and multi-service integration testing with AWS SDK v2.

Local AWS Emulation with KUMO: A Practical CI/CD Playbook for Developers

Use this practical playbook to implement production-grade CI/CD and integration testing using KUMO — a lightweight AWS emulator. We'll cover containerized runners, test isolation, end-to-end multi-service interactions, and how to mirror AWS workflows locally without incurring cloud costs. This guide targets developers and ops professionals who want reliable integration tests that run fast in CI using the AWS SDK v2.

Why KUMO?

KUMO is a lightweight AWS service emulator written in Go. It aims to be a fast, single-binary, no-auth emulator that works both in local development and CI. Compared to heavier solutions (for example, using an entire account snapshot or some LocalStack deployments), KUMO provides:

  • No authentication required — ideal for ephemeral CI environments.
  • Single binary and Docker support — easy to distribute as a container image or binary artifact.
  • Lightweight memory and startup profile — fast test feedback loops.
  • AWS SDK v2 compatibility — works well with modern Go clients and other SDKs that accept endpoint overrides.
  • Optional data persistence via KUMO_DATA_DIR — useful when you want to persist test fixtures between runs.

High-level CI/CD Patterns

The patterns below are production-focused and emphasize repeatability, isolation, and observability:

  1. Containerized runner that launches a KUMO instance scoped to the job.
  2. Test isolation with ephemeral data directories or per-test namespaces.
  3. Service mirroring with endpoint overrides and local service discovery.
  4. Network-level composition (Docker Compose or sidecar containers) to emulate multi-service interactions.
  5. Clean-up steps that ensure no state leaks between CI jobs.

Quickstart: Running KUMO Locally

Two common ways to run KUMO locally are via Docker and as a single binary. Run inside CI as a container to minimize setup complexity.

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

By default KUMO exposes AWS-like endpoints on port 4566. No credentials are required to talk to it, which simplifies CI job configuration.

Binary (dev machine)

# download kumo binary and run
./kumo --port 4566 --data-dir /tmp/kumo-data

Configuring Clients: AWS SDK v2 and Environment Hooks

Most AWS SDKs allow you to override the endpoint. For general tooling or non-Go SDKs you can use environment variables. Example environment variables to point your client at KUMO:

export AWS_ENDPOINT_URL=http://kumo:4566
export AWS_REGION=eu-west-1
export AWS_ACCESS_KEY_ID=testing
export AWS_SECRET_ACCESS_KEY=testing

For Go with AWS SDK v2, use a custom endpoint resolver so the SDK uses KUMO instead of AWS:

import (
    "context"
    "net/url"

    "github.com/aws/aws-sdk-go-v2/aws"
    "github.com/aws/aws-sdk-go-v2/config"
    "github.com/aws/aws-sdk-go-v2/service/s3"
)

resolver := aws.EndpointResolverWithOptionsFunc(func(service, region string, options ...interface{}) (aws.Endpoint, error) {
    return aws.Endpoint{
        URL:           `http://kumo:4566`,
        SigningRegion: "eu-west-1",
    }, nil
})

cfg, _ := config.LoadDefaultConfig(context.Background(), config.WithEndpointResolverWithOptions(resolver))
client := s3.NewFromConfig(cfg)

Containerized Runners: Example GitHub Actions Job

Run KUMO as a service container in GitHub Actions to isolate it per job. This pattern keeps tests hermetic and cheap.

name: CI

on: [push, pull_request]

jobs:
  test:
    runs-on: ubuntu-latest
    services:
      kumo:
        image: ghcr.io/sivchari/kumo:latest
        ports:
          - 4566:4566
        options: >-
          --health-cmd "curl -f http://localhost:4566/health || exit 1" --health-interval 10s --health-timeout 5s --health-retries 5
    steps:
      - uses: actions/checkout@v4
      - name: Run tests
        env:
          AWS_ENDPOINT_URL: http://localhost:4566
          AWS_REGION: eu-west-1
          AWS_ACCESS_KEY_ID: testing
          AWS_SECRET_ACCESS_KEY: testing
        run: |
          make test-integration

GitLab CI and other runners follow the same pattern: bring up a KUMO container as a job service and set environment variables so tests talk to it.

Test Isolation Strategies

Isolation is critical — tests must not rely on shared state. Use one of these approaches:

  • Ephemeral data directories: start KUMO with an ephemeral KUMO_DATA_DIR per job (or per test suite) so state is scoped and easy to remove.
  • Namespace patterns: prefix resource names with a unique test run ID or GUID to avoid collisions (e.g., my-bucket-test-{{CI_JOB_ID}}).
  • Reset on startup: when running local acceptance suites, call a small reset script that deletes created resources via the emulator API before tests run.

Example cleanup command (shell):

# delete all test buckets prefixed with 'ci-test-'
aws --endpoint-url=http://localhost:4566 s3 ls | awk '{print $3}' | grep '^ci-test-' | xargs -I {} aws --endpoint-url=http://localhost:4566 s3 rb s3://{} --force

Mirroring Multi-Service Interactions

Many production apps are multi-service: S3 -> Lambda -> SQS -> DynamoDB -> EventBridge. KUMO supports a broad set of services so you can orchestrate full end-to-end flows locally. Key ideas:

  1. Compose: use Docker Compose or runner services to bring up KUMO and any test helpers (e.g., test harness containers that publish messages).
  2. Use real clients: prefer calling your app's standard client code configured with endpoint overrides instead of swapping implementations for tests. This gives higher confidence.
  3. Event validation: capture events emitted by your services (SNS/SQS/EventBridge) and assert their contents using test harnesses that poll the emulator.
  4. Contract tests: run focused contract tests for each service interaction so you can isolate failures quickly without running the entire integration suite every time.

Example: running an end-to-end scenario where uploading an object to S3 triggers processing

  1. Start KUMO in the CI job.
  2. Create a bucket via your application bootstrap code or a pre-test script.
  3. Upload test object(s) via the same code path the app uses.
  4. Poll SQS or check DynamoDB for the processed result and assert expected values.

Practical CI Pipelines: Fast Feedback and Selective Runs

Large suites get slow. Use these practical approaches to keep CI fast:

  • Split tests by type: unit (fast), integration (use KUMO), and end-to-end (run sporadically or on main branch only).
  • Use matrix builds selectively: run minimal integration tests on PRs and full suites on merges to main.
  • Cache Docker images and artifacts to speed up container startup.

Observability and Debugging

Add logs, metrics, and health checks to your CI jobs. KUMO's health endpoint and quick startup make it easy to gate tests on readiness. If a failure occurs, save the emulator state directory as a job artifact for local reproduction.

Why KUMO vs LocalStack?

KUMO is a capable local emulator and often a lighter-weight alternative to LocalStack. If your team prefers a single binary with minimal resource usage and no auth complexity, KUMO is attractive. It also integrates well with AWS SDK v2 usage patterns in Go. That said, choose the tool that best fits the set of AWS services your tests exercise.

Best Practices Checklist

  • Keep KUMO in the job services so each CI job is hermetic.
  • Prefix resources with a run identifier to prevent collisions.
  • Use endpoint resolvers in SDKs (AWS SDK v2) rather than stubbing logic.
  • Persist KUMO data only when you need to reproduce state; otherwise prefer ephemeral directories and explicit resets.
  • Save emulator artifacts for failed CI jobs to aid debugging.
  • Integrate smoke checks into pipelines to fail fast if KUMO is unhealthy.

For broader resiliency patterns when working with cloud services, see our post on building resilient apps with Cloudflare and AWS. If you are testing game or simulation-heavy systems, check out our developer's guide on game verification for related test isolation ideas.

Closing: Start Small and Iterate

Introduce KUMO into a single CI job first: run a few critical integration tests that exercise your most important service boundaries. Once that stabilizes, expand coverage and add multi-service end-to-end tests. KUMO's lightweight footprint, AWS SDK v2 compatibility, and Docker support make it a practical tool for teams wanting reliable integration tests without the cost of running AWS for every CI job.

Ready to try? Spin up a KUMO service in your CI, add an endpoint override, and migrate one integration test to run against the emulator. You'll save cloud costs and gain much faster feedback.

Advertisement

Related Topics

#DevOps#Testing#Cloud
U

Unknown

Contributor

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-08T11:33:40.827Z