It's 2pm. You need to ship a fix before end of day. You run the integration suite and it fails — not because your code is wrong, but because staging is down. Someone else's bad migration took it out an hour ago, and now you're in the "is it up yet" channel with six other engineers, watching a thread instead of shipping.
Sound familiar? This is the actual, daily cost of how most teams do integration testing. And it usually comes down to one of two bad options.
The two options, and why both are bad
Mock everything. Fast, deterministic, runs anywhere — and proves almost nothing. Your mock says Postgres returns rows in this shape. Real Postgres doesn't care what your mock thinks. The bug that matters — the one your mock can't see by definition — ships to production and pages someone at 2am.
Share a staging environment. Real dependencies, finally — but now you're queued behind whoever's deploying, debugging, or has just quietly broken it for everyone. It's slow, it's flaky in ways that have nothing to do with your code, and "is staging even up right now" becomes a real question you ask multiple times a week.
Neither of these is a testing strategy. They're both just different ways of accepting risk.
There's a third option: real dependencies, but yours alone
Morarix is a CLI that reads a small, hand-authored dependency graph for your service and provisions the real thing — Postgres, Redis, Kafka, and eight AWS services via LocalStack — as disposable, isolated containers on your laptop or in CI. Not a shared environment you wait for. Not a mock you have to trust. The real dependency, health-checked, torn down when you're done, every time.
morarix init # scaffold morarix.graph.json
morarix import compose # or: convert an existing docker-compose.yml
morarix up # provision + validate — real Postgres, Redis, S3... on localhost
Then you run your existing test suite — completely unmodified — against those real dependencies. Same commands, locally and in CI.
Show, don't tell
Here's the whole morarix.graph.json for a FastAPI service backed by Postgres, Redis, and S3 (one of the reference examples):
{
"schema_version": "1.0",
"service": { "name": "python-fastapi", "repo_path": ".", "language": "python", "framework": "fastapi" },
"dependencies": [
{ "id": "db", "type": "postgres", "fidelity": "real", "source": "manual",
"required_env_vars": ["MORARIX_DB_CONNECTION_STRING"], "optional": false,
"image": "postgres", "version": "16" },
{ "id": "cache", "type": "redis", "fidelity": "real", "source": "manual",
"required_env_vars": ["MORARIX_CACHE_CONNECTION_STRING"], "optional": false,
"image": "redis", "version": "7" },
{ "id": "assets", "type": "s3", "fidelity": "real", "source": "manual",
"required_env_vars": ["MORARIX_ASSETS_HOST", "MORARIX_ASSETS_PORT"], "optional": false,
"resource": { "bucket_name": "widget-assets" } }
]
}
That's it. No YAML you have to hand-sync with your CI config. fidelity: "real" means Morarix actually provisions a container and health-checks it — not "the process started," but "Postgres will accept a connection," "Redis responds to PING," "the LocalStack S3 endpoint is reachable."
Here's the actual output of running it — nothing hand-written for this post:
$ morarix up
morarix: loaded 3 dependencies for "python-fastapi"
- db postgres fidelity=real
- cache redis fidelity=real
- assets s3 fidelity=real
morarix: environment ready (run_id=morarix-3f16480cfbc9-1786016512, mode=isolated) — morarix.connections.json and .env.morarix written
$ pytest -v
============================= test session starts =============================
collecting ... collected 9 items
tests/test_api.py::test_health_reports_ok PASSED [ 11%]
tests/test_api.py::test_create_widget_then_list_returns_it PASSED [ 33%]
tests/test_api.py::test_get_widgets_is_cached_across_consecutive_calls PASSED [ 44%]
tests/test_data_access.py::test_insert_and_list_widgets_round_trips_through_postgres PASSED [ 77%]
tests/test_data_access.py::test_cache_set_and_get_round_trips_through_redis PASSED [ 88%]
tests/test_data_access.py::test_spec_upload_and_download_round_trips_through_s3 PASSED [100%]
======================= 9 passed, 3 warnings in 24.13s ========================
$ morarix down
morarix: environment torn down (was: isolated)
No compose file in the app repo. No mocks. No manual container wrangling. Just the real dependencies, up, tested against, and gone.
"Isn't this just docker-compose / Testcontainers / Tilt?"
Fair question — here's the actual difference:
-
vs.
docker-composeby hand — compose has no fidelity concept (a service is eitherrealor entirely absent), no per-type health checks (depends_onisn't "Postgres will actually accept a connection"), and nothing stops your compose file and your CI YAML from silently drifting apart over time. -
vs. Testcontainers — Testcontainers is a library embedded in your test code, per language, with its own API to learn per dependency type. Morarix is a CLI: one graph, one
morarix up, zero test-code changes, and the same graph works across every language in a polyglot org instead of being re-implemented per service. - vs. Tilt / Skaffold / Garden — those solve your whole live-reload dev loop, usually against Kubernetes, often building and deploying your app itself. Morarix deliberately doesn't touch your app — it only provisions what's around it, so your app keeps running exactly how you already run it.
The same three commands in CI
This is the actual payoff — not a separate CI-specific setup that quietly drifts from what you run locally, but the literal same commands:
- name: Install morarix
run: go install github.com/morarixhq/morarix/cmd/morarix@latest
- run: morarix up
- run: pytest
- run: morarix down
ubuntu-latest already has Docker. That's the whole prerequisite.
Get it
go install github.com/morarixhq/morarix/cmd/morarix@latest
Prebuilt binaries for Linux, macOS, and Windows (amd64 + arm64) are on the v0.1.0 release — no Go toolchain required.
Currently working end-to-end for Go, Node.js, TypeScript, Java, .NET, and Python, with six runnable reference examples covering both onboarding paths (init from scratch and import compose from an existing docker-compose.yml), plus Postgres, MySQL, Redis, Kafka, REST, and LocalStack health checkers already built in.
Try it, then tell me where it breaks
This is genuinely early — v0.1.0, not a polished v3. If you've got a service with a Postgres/Redis/Kafka dependency sitting behind mocks or a shared staging environment you're tired of waiting on, that's exactly the case this is for. Point it at that service and see what breaks.
- ⭐ Repo: github.com/morarixhq/morarix
- 📖 Why Morarix (the full case): morarix-docs/concepts/why-morarix.md
- 🧭 Usage guide: morarix-docs/docs/usage-guide.md
- 🧪 Examples: morarix-examples
If it saves you a "is staging up" Slack thread, a star helps other people find it. If it breaks on your setup, open an issue — that's exactly the feedback this stage needs.
Top comments (0)