Skip to main content

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 runtime describe-* 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-instances returns a working endpoint.
  • elasticacheversion selects the container image tag (the default emulator maps redis versions to the major tag: 7.2redis:7-alpine). Engine valkey requires mayfly's patched emulator image; memcached listens 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 / GetBootstrapBrokers all answer correctly. topics are 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: true entries 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; use generate: when the app just needs a secret to exist. Apps can fetch at runtime via the SDK (GetSecretValue against the injected AWS_ENDPOINT_URL) — the AWS-native pattern — or consume the mirrored k8s Secret.

Secrets: the app contract

ServiceSecretKeys
s3s3-bucketsBUCKETS, S3_ENDPOINT
rdsrds-<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
mskmsk-<name>KAFKA_BROKERS
dynamodbdynamodb-<name>TABLE_NAME, HASH_KEY, DYNAMODB_ENDPOINT
albalb-<name>ALB_URL, ALB_DNS_NAME, ALB_HOST, ALB_TARGET_APP, ALB_PUBLIC_URL*
secretsmanagersm-<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.