mayfly

Ephemeral environments.
Delightfully fast.

One YAML spec spins up a test environment in an isolated Kubernetes namespace: an emulated cloud harness — AWS (S3, RDS, ElastiCache, Kafka, DynamoDB) and Azure (Key Vault, Postgres, SQL) — plus your apps, talking to it with the SDKs they already use.

Spin up. Test. Tear down. A TTL reaper destroys anything left behind.

lives fast. gone by sunset.
$ mayfly up env.yaml
mayfly 0.2.0 · ephemeral by design
✓ namespace merry-blonde-stoat created 0.3s
✓ postgres (appdb) ready 5432 1.1s
✓ redis ready 6379 1.2s
✓ kafka (msk) ready 9092 2.1s
✓ s3 (emulated) ready 4566 2.3s
✓ api (your app) deployed 8080 4.8s
Environment ready in 6.2s · ttl 8h · gone by sunset
Namespace: merry-blonde-stoat
Endpoints written to Kubernetes Secrets
$

One spec, full stack

Declare S3 buckets, RDS databases, ElastiCache, Kafka topics, Key Vaults, and app deployments in one YAML file. In-cluster AWS and Azure emulators play the cloud — your apps can't tell. Everything spins up together. Everything tears down together.

Truly isolated

Each environment is one Kubernetes namespace, deterministically named from a seed. Teardown is namespace deletion — no leftovers, ever.

Self-cleaning

TTLs on everything. mayfly reap and the reaper delete expired environments automatically. Live fast, clean fast. Leave no trace.

/ how it works

apiVersion: mayfly/v1alpha1
seed: pr-1234 # env name derives from this
ttl: 8h # reaped after this
emulator:
kind: ministack # or floci
services:
s3:
buckets: [assets, uploads]
rds:
- name: appdb
engine: postgres
dbName: app
elasticache:
- name: cache-a
msk:
- name: events
topics: [orders]
keyvault: # azure, via floci-az
- name: app-secrets
apps:
api:
image: ghcr.io/acme/api:pr-1234
port: 3000
secrets: [rds-appdb, elasticache-cache-a]

> Local emulation, cloud-compatible

AWS runs in-cluster behind http://aws:4566 — MiniStack or floci, your pick.
Azure runs on floci-az behind http://azure:4577.
Swap the backend if you like. Your apps don't care.

> No Docker socket. No privileged pods.

We don't mount your Docker socket.
We don't need privileged pods.
We don't touch real AWS or Azure.
Sleep well.

> Secrets as the contract

Every service's endpoints and credentials are delivered as Kubernetes Secrets. Your apps consume Secrets. That's it.

> Deterministic naming

Names derived from the seed.
Predictable, shareable, scriptable.
Perfect for PRs and previews.

/ cli reference

mayfly up env.yaml
Create or update the environment from a spec (--seed/--set for per-PR variants)
mayfly status env.yaml
Pods + provisioned secrets
mayfly list
All mayfly environments, age + TTL
mayfly render env.yaml
Print the resolved plan, touch nothing
mayfly extend env.yaml --ttl 4h
Push expiry out
mayfly restart env.yaml
Rolling-restart apps (after re-pushing the same tag)
mayfly down env.yaml
Teardown now (namespace delete)
mayfly reap
Delete every expired environment

/ install

Requires: kubectl + any Kubernetes cluster (k3d is plenty).

$ uv pip install mayfly-cli
$ mayfly version
mayfly 0.2.0

Or: pip install mayfly-cli