Services
Each service class supports backend: auto | emulator | native per entry:
- emulator — provisioned through the real AWS API against the
in-namespace emulator (
create-db-instance,create-cache-cluster, ...), so runtimedescribe-*calls answer truthfully. - native — a plain pod + Service deployed directly by mayfly.
- auto (default) — emulator where the chosen emulator supports the class honestly, else native. The Secret contract is identical either way.
services:
s3:
buckets: [assets, uploads]
rds:
- name: appdb
engine: postgres # postgres | mysql | mariadb
dbName: app
elasticache:
- name: cache-a
engine: redis # redis | valkey | memcached
version: "7.2" # engine version -> image tag
msk:
- name: events
topics: [orders]
dynamodb:
- name: sessions
hashKey: id # default "id"
alb:
- name: hello-alb
targetApp: hello # must be an apps: key
secretsmanager:
- name: app/api-key
value: "test-key-123" # literal fixture
- name: app/signing-key
generate: true # random per env; kept across re-ups
Notes per class
- s3 — in-process in the emulator; instant.
- rds — on the default emulator this is the real RDS API: the instance
is an actual postgres container spawned via kubedock, and
describe-db-instancesreturns a working endpoint. - elasticache —
versionselects the container image tag (the default emulator maps redis versions to the major tag:7.2→redis:7-alpine). Enginevalkeyrequires mayfly's patched emulator image;memcachedlistens on 11211 with its own secret keys. - msk — hybrid: mayfly deploys a real Redpanda broker natively, then
registers the cluster through the MSK control-plane API, so
ListClusters/DescribeCluster/GetBootstrapBrokersall answer correctly.topicsare created at provision time. - dynamodb — in-process; emulator-only (no native backend exists).
- alb — an emulated ALB with a working data plane; see the Internal ALBs guide.
- secretsmanager — in-process; emulator-only. Literal
value:entries converge to the spec on re-up;generate: trueentries get a random value on first creation and are never rotated by re-ups. Values in a committed spec are test fixtures — don't put production credentials there; usegenerate:when the app just needs a secret to exist. Apps can fetch at runtime via the SDK (GetSecretValueagainst the injectedAWS_ENDPOINT_URL) — the AWS-native pattern — or consume the mirrored k8s Secret.
Secrets: the app contract
| Service | Secret | Keys |
|---|---|---|
| s3 | s3-buckets | BUCKETS, S3_ENDPOINT |
| rds | rds-<name> | DATABASE_URL, DB_HOST, DB_PORT, DB_USER, DB_PASSWORD, DB_NAME |
| elasticache (redis/valkey) | elasticache-<name> | CACHE_ENGINE, REDIS_URL, REDIS_HOST, REDIS_PORT |
| elasticache (memcached) | elasticache-<name> | CACHE_ENGINE, MEMCACHED_HOST, MEMCACHED_PORT |
| msk | msk-<name> | KAFKA_BROKERS |
| dynamodb | dynamodb-<name> | TABLE_NAME, HASH_KEY, DYNAMODB_ENDPOINT |
| alb | alb-<name> | ALB_URL, ALB_DNS_NAME, ALB_HOST, ALB_TARGET_APP, ALB_PUBLIC_URL* |
| secretsmanager | sm-<mangled-name> | SECRET_NAME, SECRET_ARN, SECRET_VALUE |
* present when the cluster has Traefik (k3s/k3d) for browser access.
Endpoints in secrets are always cluster-internal
servicename:standard-port (rds-appdb:5432, elasticache-cache-a:6379,
msk-events:9092), uniform across backends. For emulator-backed services
mayfly creates that Service selecting the spawned pod directly, so data
traffic goes pod-to-pod and survives emulator restarts — while the AWS
API's own published-port answers (aws:15432) stay valid too.