Skip to content

Developer Productivity

Docker Compose vs mise/asdf — Local Dev Environment Choice in 2026

Docker Compose is reproducible but glacial on Mac (container overhead + Docker Desktop). mise (formerly rtx) and asdf manage runtimes natively, instant startup. Benchmarks + setup. Aidxn rule: mise for JS/TS dev, Docker when your stack needs Postgres + Redis reproducibility.

🐳 🎯

Local development environments come in two flavours in 2026. First: Docker Compose — containerise everything (Node, Postgres, Redis, Nginx), guarantee it runs identically in production and on every developer's Mac. Second: mise + asdf — manage runtimes (Node, Python, Go) natively on your Mac, skip container overhead, get instant command startup. Docker wins on reproducibility; mise wins on speed. Which one should you reach for? The answer depends on what your stack does. If you're building a pure Node/TypeScript app, mise is a no-brainer. If your local dev needs a Postgres database + Redis cache + a reverse proxy running in parallel, Docker Compose is the right call — just budget for slowness on Mac and mitigate it. Aidxn's rule: mise for single-runtime apps (Node, Python, Rust — one language, one main process), Docker Compose when you need a multi-service reproducible stack. Here's how to choose and set both up.

Definitions: What Each Tool Does

Docker Compose: a YAML config (docker-compose.yml) that declares services (containers) and their interdependencies. Run docker-compose up, Docker spins up isolated containers for Node, Postgres, Redis, etc. Identical setup every time, identical in dev and production. Price: Docker Desktop on Mac runs a lightweight Linux VM, adds ~500ms to container startup, ~200ms per command because it bridges between Mac and VM. That's not a bug — it's the tradeoff for reproducibility.

mise (formerly rtx): a Rust-based version manager that installs language runtimes (Node, Python, Ruby, Go, Rust, Erlang) onto your Mac. mise use node@20.10 switches Node to 20.10 globally or per-project. Zero container overhead, instant startup, native Mac binaries. Tradeoff: if your app needs Postgres, you install it separately (via Homebrew) and manage its lifecycle manually — no automatic Docker containers spinning up.

asdf: the older sibling of mise. More plugins, larger community, slower (Bash-based instead of Rust). Mise is asdf-compatible (reads .tool-versions files) and faster. If you're starting fresh, choose mise.

Approach 1: mise — Native Runtime Management for Fast Dev

Speed Benchmarks

On a 2024 MacBook Pro (M4 Max):

Docker Compose: docker-compose up with 3 services (Node, Postgres, Redis) = 6–8 seconds. Every docker-compose down/up cycle = 8 seconds lost. Build a feature 10 times a day, that's 80 seconds (1+ minute per day, ~8 hours per year).

mise: mise install (one-time) = 2 seconds. node startup = 0.1ms (native binary). Switching versions via .tool-versions = instant. npm install still takes 30–60 seconds (network, not runtime).

Winner: mise by 60–100x for iteration cycles.

Setup: .tool-versions + mise install

Create a .tool-versions file in your project root:

node 20.10.0 python 3.12.0 pnpm 9.0.0

Then:

mise install # Install declared versions into ~/.mise/installs/ mise use node@20.10.0 # Switch to 20.10 for this project node --version # v20.10.0 cd ../another-project # Switch to another folder node --version # Different version from that project's .tool-versions

Every time you cd into a project, mise auto-switches runtimes based on .tool-versions. Transparent, instant, no mental overhead.

When mise Breaks Down

You need a Postgres database running locally. Option 1: install Postgres via Homebrew (brew install postgresql), manage brew services start postgresql manually. Works, but you're now responsible for database lifecycle. Option 2: run Postgres as a Docker container (better isolation) and use mise for Node. Hybrid approach — common in 2026.

Approach 2: Docker Compose — Reproducible Multi-Service Stack

When to Use It

Your app needs Postgres + Redis + maybe a reverse proxy (Nginx, Traefik) running simultaneously. Docker Compose guarantees all three start in the correct order, shut down together, and run with identical settings every time. A teammate clones your repo and docker-compose up runs their entire stack. No "works on my Mac" bugs. Cost: Docker Desktop overhead + 6–8 seconds per restart.

A Real Example: Node + Postgres + Redis

version: '3.8' services: app: build: context: . dockerfile: Dockerfile ports: - "3000:3000" environment: DATABASE_URL: postgres://user:password@postgres:5432/myapp REDIS_URL: redis://redis:6379 depends_on: - postgres - redis volumes: - ./src:/app/src # Live reload on code changes - node_modules:/app/node_modules # Keep node_modules off your Mac filesystem postgres: image: postgres:16-alpine environment: POSTGRES_USER: user POSTGRES_PASSWORD: password POSTGRES_DB: myapp ports: - "5432:5432" volumes: - postgres_data:/var/lib/postgresql/data redis: image: redis:7-alpine ports: - "6379:6379" volumes: postgres_data: node_modules:

Run it:

docker-compose up # Start all three services docker-compose down # Stop and remove containers docker-compose logs app # Tail app logs

Every developer, CI/CD pipeline, production — identical stack. Postgres version 16, Redis 7, Node from your Dockerfile. No version drift.

The Mac Performance Gotcha

Docker Desktop on Mac runs a lightweight Linux VM. File I/O between Mac and containers is slow (Docker Desktop can sync volumes, but it's not instant). For Node apps with node_modules, two solutions:

1. Named volumes (recommended): volumes: node_modules:/app/node_modules — keep node_modules inside the container, not synced to Mac. Your editor (VS Code) can't see it, but that's fine (you don't edit node_modules anyway). Build/run is fast.

2. VirtioFS (Docker Desktop setting): improves Mac-to-VM file sync. Still slower than native, but acceptable. Check Docker Desktop settings → Resources → File Sharing.

Approach 3: Hybrid — mise for App Dev, Docker for Postgres

Best-of-both-worlds pattern: use mise to manage Node, run Postgres in Docker.

version: '3.8' services: postgres: image: postgres:16-alpine environment: POSTGRES_USER: user POSTGRES_PASSWORD: password POSTGRES_DB: myapp ports: - "5432:5432" volumes: - postgres_data:/var/lib/postgresql/data volumes: postgres_data:

Then:

mise install docker-compose up postgres # Start only Postgres npm install && npm run dev # Run Node natively on your Mac (instant startup) DATABASE_URL=postgres://localhost npm run migration # Migrate as needed

Benefit: Node dev loop is instant (no container overhead). Postgres is reproducible and persistent. Code changes hot-reload immediately because Node runs on your Mac. This is Aidxn's default for web apps.

Dependency Hell — mise vs Docker vs npm

Three ways a project can break when versions drift:

Scenario 1: Node version mismatch. Developer A uses Node 18, Developer B uses Node 20. Some npm packages compile differently. Mise: .tool-versions ensures everyone runs Node 20. Docker: Dockerfile specifies Node 20; both devs get Node 20. npm alone: everyone's on whatever they have installed (chaos).

Scenario 2: npm dependencies. Someone runs npm install with npm 9, someone else with npm 10. Lockfile format changes, conflicts happen. Solution: npm ci --frozen-lockfile (both approaches). No advantage to Docker here.

Scenario 3: System libraries (OpenSSL, libc, build tools). Postgres needs OpenSSL; version mismatch causes build failures. Docker isolates the OS version, so it's guaranteed identical. Mise: you inherit your Mac's system libraries. Problem if your team is on macOS 13 and 14 (different OpenSSL versions). Docker wins here.

Aidxn's move: For pure JavaScript/TypeScript (no native compilation), mise + .tool-versions. For projects with Postgres, Redis, or heavy native compilation, Docker Compose (either full or hybrid).

Setup Checklist: Which Path to Choose?

Choose mise if: You're building a Node/Python/Go app with no database or cache layer in local dev. Your team all uses Mac. You want instant feedback loops and hot-reload iteration. Acceptable: you manage Postgres separately if needed.

Choose Docker Compose if: Your app requires 2+ services running in parallel (Postgres + Redis, or multiple microservices). You have Windows developers or a heterogeneous team. Reproducibility is more important than startup speed. Acceptable: 6–8 second restarts.

Choose hybrid if: You're OK with one-off setup (Docker for Postgres, mise for Node). Most flexible, gets 80% of the wins with minimal overhead. Aidxn default.

Six FAQs

Does Docker Compose slow down every command or just startup?

Just startup. Once containers are running, docker-compose up does nothing (containers stay up). Slow part: docker-compose down/up cycle (6–8 seconds). During active development, you rarely stop/start unless troubleshooting or switching branches. But the first time you run docker-compose up in a session, budget 8 seconds.

Can I use mise with a monorepo?

Yes. Each workspace folder can have its own .tool-versions. mise respects the closest .tool-versions in the directory tree. So workspace-a can use Node 20, workspace-b can use Node 22.

Is asdf dead? Should I learn mise instead?

asdf is alive (still widely used), but mise is faster and actively developed. If you're starting fresh, learn mise. If asdf already works for your team, no rush to migrate. mise can read asdf's .tool-versions files directly.

How do I use Docker Compose in CI/CD?

In GitHub Actions, GitHub provides Docker (Docker daemon already installed). Run docker-compose up -d in your workflow, run tests, docker-compose down to clean up. Same YAML as local dev — that's the whole point.

Can I use both mise and Docker Compose in the same project?

Yes (the hybrid approach). Mise for host Node, Docker for Postgres. Or use mise to manage Node version, then docker-compose to orchestrate multi-service setup. No conflict.

What if my team is split (some Mac, some Linux, some Windows)?

Docker Compose is the only option. It guarantees identical environments across all three platforms. Mise is Mac-specific (though versions exist for Linux). If you have Windows devs, Docker is non-negotiable.

The Bottom Line

Docker Compose is slow on Mac but bulletproof for reproducibility. Mise is instant but requires manual management of databases. The trend in 2026 is hybrid: use mise for single-language app development, Docker for stateful services (Postgres, Redis, queues). This gets you 95% of the speed benefit of mise with 95% of the reproducibility benefit of Docker. Set up a .tool-versions in your project, run mise install, then use docker-compose only for Postgres (if needed). Most importantly: measure your own setup. Benchmark your restart cycle (with and without Docker), share the numbers with your team, pick the tool that matches your pain point. Cargo cult tooling (using Docker because everyone does, or skipping it because you think it's slow) costs more than the tool itself.

Standardising dev environments across a team? See developer experience consulting to audit your stack and proposal improvements, or go deeper into Mac dotfiles to bootstrap every machine identically.

Let us make some quick suggestions?

Please provide your full name.
Please provide your phone number.
Please provide a valid phone number.
Please provide your email address.
Please provide a valid email address.
Please provide your brand name or website.
Please provide your brand name or website.