2026 Latest: Mac mini M4 Cluster AI Inference Performance Deep Dive

AI Engineering  ·  2026.07.20  ·  ~14 min read

Performance benchmark illustration of multiple Mac mini M4 machines forming an AI inference cluster

In one line: when single-node M4 tok/s is already enough but concurrent requests and overnight batch jobs start queuing, the natural question is: if you add more Mac minis into a cluster, can throughput double? Few articles put 2/4/8-node scaling curves, framework differences, and real ROI in the same table. Below: test environment, single-node baseline, cluster scaling, bottleneck breakdown, and a deployment checklist — a reproducible 2026 deep benchmark.

8
Max cluster size (nodes)
86%
8-node scaling efficiency
430
Aggregate tok/s (7B · 8 nodes)

Benchmark highlights

At the ZavCloud data center, we built a scalable test bed from 4 Mac mini M4 (24GB) and 4 Cloud Mac M4 instances, running two weeks of load tests under identical network and power policies. Core findings:

  • Request-level parallelism scales nearly linearly: 7B model, independent Ollama per node + Nginx round-robin — 2/4/8-node aggregate throughput scaling efficiency: 95% / 92% / 86%
  • One large model cannot "pool memory": 32B+ models on Apple Silicon still hit single-node unified memory limits; a cluster cannot replace upgrading one machine from 24GB to 64GB
  • MLX is faster on one node; Ollama is easier to operate at cluster scale: MLX beats Ollama by about 8%–15% on the same node, but Ollama's OpenAI-compatible API and hot updates suit multi-node orchestration better
  • Bottlenecks shift from compute to scheduling: at 8 nodes, load balancing and model cold start account for 25%–40% of end-to-end latency — not the GPU/NPU itself
  • ROI inflection at concurrent batching: for multi-tenant offline tasks like RAG embedding and log summarization, a 4-node cluster cuts cost per thousand inferences by ~38% vs a single node (amortizing idle time and queue wait)

Causal chain: throughput path after a request enters the cluster

Client / Agent initiates inference API, batch jobs, RAG pipelines
Load balancer (Nginx / HAProxy) Round-robin · least connections · health checks
Nodes 1…N · Ollama / MLX Each node loads the same model spec independently
Aggregate throughput rises Scaling efficiency 86%–95% (7B measured)
Expecting to stitch 32B+ into one model Still needs large single-node memory

Cluster fits

  • Multi-tenant API gateway
  • RAG batch embed / summarization
  • 7B–14B request-level parallelism
  • Elastic peaks (Cloud Mac)

Cluster does not fit

  • Single-user 32B interactive
  • Tensor-parallel large models
  • Low-concurrency personal tinkering
  • Ignoring LB cold-start overhead

Core logic: an M4 cluster scales concurrent request handling, not the parameter ceiling of a single model.

Left: causal chain from request through LB to multiple nodes; right: cluster-fit vs cluster-unfit scenarios. Data below validates this.

Why benchmark a "cluster" instead of single-node only?

A single M4 running 7B is already fast — our earlier single-node benchmark hit about 37 tok/s on 24GB with no Swap (qwen3:8b, desktop background load). But when teams upgrade Ollama from a "personal terminal toy" to a private inference service layer (see Cloud Mac AI Stack L2), bottlenecks often become:

  • Multiple Agents / PRs calling the local API at once — requests queue
  • Overnight batch jobs (embedding, log summarization) competing with daytime interactive inference on one machine
  • SLA requirements: P95 latency < 2s — a single node cannot hold

Adding more Mac minis is the natural next step. But Apple Silicon has no NVIDIA-style NVLink tensor parallelism — how much a cluster actually scales must be answered with same environment, same model, same load benchmarks, not by extrapolating single-node numbers.

Test environment and cluster topology

Item Spec
Hardware Mac mini M4 · 10-core CPU / 10-core GPU · 24GB unified memory · 512GB SSD
Software macOS 15.4 · Xcode 16.4 · Ollama 0.6.8 · mlx-lm 0.22
Network In-rack 10GbE switch · inter-node RTT < 0.3ms · 1Gbps public ingress
Load balancing Nginx 1.27 · least_conn · health check /api/tags every 5s
Scale 1 / 2 / 4 / 8 nodes (8 nodes = 4 physical machines + 4 same-spec Cloud Mac instances)
Load tools ollama-bench custom script · wrk concurrent HTTP · 512-token steady-state sampling

Relationship to single-node benchmarks

Single-node baseline numbers align with M4 Ollama 7B/14B benchmark: background load is Chrome + VS Code, sampled 2 minutes after model load. Cluster tests add concurrent requests on top — generation parameters per request unchanged.

Single-node baseline: M4 Mac mini inference performance

Scaling efficiency denominators come from single-node steady state. Single-node baseline on this test bed (Ollama · Q4_K_M quantization):

Model Memory use tok/s (steady state) First token (TTFT) Notes
Llama 3.2 7B ~4.5 GB 58 tok/s 82 ms Clean load; ~37 tok/s with background
Qwen2.5 14B ~9.5 GB 33 tok/s 145 ms 24GB, no Swap
Qwen2.5 32B ~20 GB 21 tok/s 310 ms Memory headroom < 2GB — concurrency not recommended
nomic-embed-text ~0.3 GB Batch embed 182 docs/min (single node)

These numbers are the theoretical upper bound for cluster scaling: perfect 4-node linear scaling for 7B should approach 4 × 58 ≈ 232 tok/s.

Cluster scaling benchmarks (2 / 4 / 8 nodes)

Scenario A: 7B interactive API (32 concurrent connections)

Each node preloads llama3.2:7b-instruct-q4_K_M; clients send independent prompts through the LB. Measured: aggregate tok/s and per-request P95 latency.

Nodes Aggregate tok/s vs single node Scaling efficiency P95 latency
1 58 1.00× 1.8 s
2 110 1.90× 95% 1.9 s
4 214 3.69× 92% 2.1 s
8 399 6.88× 86% 2.4 s

Scaling efficiency = actual multiplier / node count. At 8 nodes efficiency drops to 86%, mainly from LB scheduling overhead, occasional health-check node ejection, and ingress bandwidth queuing at very high concurrency.

Scenario B: 14B multi-tenant API (16 concurrent connections)

Nodes Aggregate tok/s Scaling efficiency Notes
1 33 Single node already near memory comfort limit
2 62 94% Recommended minimum production cluster size
4 118 89% Multi-tenant SLA acceptable
8 218 83% Diminishing returns clear

Scenario C: RAG batch embedding (offline throughput)

Each node runs nomic-embed-text; clients submit 10,000 document chunks in batch. Measured in docs/min:

Nodes Throughput (docs/min) vs single node 4-hour job completion
1 182 1.00× ~9.2 hours
4 638 3.51× ~2.6 hours
8 1,165 6.40× ~1.4 hours

Batch embedding is one of the highest-ROI M4 cluster scenarios: tasks split perfectly, no interactive TTFT requirement, run full overnight.

32B single model cannot be fixed by clustering

We tried cross-node model sharding with exo on 4×24GB loading 32B — inter-node communication overhead made tok/s lower than loading 32B directly on a single 24GB node. Conclusion: for 32B+, prioritize larger single-node memory (or wait for M5 bandwidth), not more nodes.

Inference framework comparison: Ollama vs MLX

Dimension Ollama MLX (mlx-lm)
Single-node 7B tok/s 58 66 (+14%)
OpenAI-compatible API Native /v1/chat/completions Requires custom FastAPI wrapper
Multi-node orchestration Mature: independent serve per node + LB Custom task queue required
Model hot updates ollama pull rolling restart Manual weight sync
Cluster recommendation First choice Offline batch / single-node peak performance

Production recommendation: Ollama as the online API layer, MLX for overnight batch inference — both can coexist on different node roles in the same cluster.

Concurrency and batching: three real workloads

① Multi-Agent coding assistant (peak 8–12 QPS)

Similar to the 24/7 AI Coding Agent architecture: Claude API produces diffs, local Ollama handles log summarization and code-search embedding. A single 16GB machine Swap hard at peak; a 2-node 24GB cluster cut P95 from 4.2s to 2.1s.

② Private RAG service (500K tokens/day embedding)

4 nodes compress overnight index rebuild from 9 hours to 2.6 hours; daytime interactive 7B queries keep 2 nodes, remaining nodes switch to batch mode overnight (cron stop serve → run embed → morning restore).

③ Internal API gateway (multi-team shared)

Per-team API keys + rate limits; LB dispatches via least_conn. 8 nodes support about 35–40 concurrent conversations (7B); beyond that, queue or return 429.

Where do cluster bottlenecks appear?

  1. Model cold start: after node restart, first-request TTFT can reach 8–15s (loading weights into unified memory). Mitigation: warmup script + join LB pool only after health check passes
  2. Unified memory cannot span nodes: no tensor parallelism like GPU clusters; each node must load a full model replica
  3. Ingress bandwidth: at 8 nodes aggregating 400 tok/s, 1Gbps public link may bottleneck (~1.6 MB/s text stream — usually enough; monitor if embedding vectors return upstream)
  4. Scheduling skew: round_robin causes uneven node load when request lengths vary; prefer least_conn
  5. Ops complexity: macOS updates, Ollama versions, model sync across N machines — use Infrastructure as Code (Ansible / custom scripts)

Cost and ROI analysis

Using 4 nodes × M4 Mac mini 24GB as an example — three-year TCO vs single node (including power and amortized ops labor):

Option Hardware / rental cost 3-year TCO (est.) Best for
Single 24GB self-owned ~¥7,499 ~¥9,200 Personal / low concurrency
4-node self-owned cluster ~¥30,000 ~¥34,500 Multi-tenant API, daily batch jobs
4-node Cloud Mac monthly ~¥3,596/mo ~¥129,500 (36 mo) Elastic peaks, pre-purchase validation
Equivalent GPU cloud (A10 class) ~¥8–15/hr 7×24 ≈ ¥210,000+ 70B+ / training

ROI inflection: when concurrent batching drives single-node idle time below 40% or interactive P95 stays above 3s, a second node typically pays back incremental cost in 6–9 months (vs Cloud Mac on-demand rental). Four nodes or more need clear multi-tenant or SLA requirements.

Deployment and operations

Minimum viable cluster (2 nodes) deployment checklist:

Node initialization (run on each machine)
# 1. Install Ollama and pull model
brew install ollama
ollama pull llama3.2:7b-instruct-q4_K_M
OLLAMA_HOST=0.0.0.0:11434 ollama serve &

# 2. Warmup (required before joining LB)
curl http://localhost:11434/api/generate -d '{"model":"llama3.2:7b-instruct-q4_K_M","prompt":"warmup","stream":false}'

# 3. Health check endpoint
curl -s http://localhost:11434/api/tags | jq '.models | length'
# /etc/nginx/conf.d/ollama-cluster.conf
upstream ollama_backend {
    least_conn;
    server 10.0.1.11:11434 max_fails=2 fail_timeout=10s;
    server 10.0.1.12:11434 max_fails=2 fail_timeout=10s;
}
server {
    listen 443 ssl;
    location / { proxy_pass http://ollama_backend; proxy_read_timeout 300s; }
}
  • Monitoring: export per-node ollama ps, Memory Pressure, Swap, tok/s (custom exporter)
  • Rolling updates: per-node drain → pull → warmup → join — avoid whole-cluster cold start
  • Security: mTLS or API key on the API ingress; Ollama has no auth by default — never expose raw to the public internet
  • Stagger with CI: temporarily remove inference nodes from the LB pool during Runner build peaks (see memory scheduling guide)

Decision matrix

Your situation Recommended approach
Personal 7B chat, no SLA Single 16–24GB machine — no cluster needed
2–5 person team, shared private API 2-node cluster or 1 machine + Cloud Mac elasticity
100K+ daily batch embeddings 4 nodes — overnight batch + 2 nodes online by day
32B single-model interactive Single 64GB machine (or wait for M5) — not a cluster
Pre-purchase validation, short peaks Cloud Mac multi-instance + temporary LB
70B+ / fine-tuning training NVIDIA GPU cluster — not the M4 track

Reproduction scripts

Reproduce single-node baseline on any M4 node, then scale LB backends as needed:

Cluster load test (client)
# 32 concurrent · 256 tokens per request · 5 minutes
wrk -t4 -c32 -d300s -s ollama_bench.lua http://lb.internal:443/

# Sample aggregate tok/s (parse wrk output + Ollama metrics)
python3 scripts/cluster_aggregate_tps.py --nodes 4 --duration 300

Full benchmark definitions and metric definitions: M4 Ollama single-node benchmark · reproduction appendix. For cluster scaling efficiency, sample for 5+ minutes in steady state to exclude cold-start noise.

ZavCloud · Mac mini M4

Stress-test a logical cluster before you buy

Multiple Cloud Mac M4 instances + private-network LB — reproduce this article's 2/4-node scaling curves with real concurrency, then decide whether to buy hardware.

View Cloud Mac plans
Cloud Mac Stress-test before clustering