Abbeal

Architecture

MACH Architecture: The Integration Guide for CTOs.

Microservices, API-first, Cloud-native, Headless. What MACH really changes, when to migrate from a monolith, integration pitfalls, and how we delivered it in luxury retail with an 18-month ROI.

11 min

Your e-commerce monolith has been holding up for 5 years, but each new market takes 6 months to deliver, your team of 40 devs is stepping on each other's toes, and the business wants to test a new recommendation engine without waiting for the quarterly release. You've heard about MACH, maybe via commercetools or Contentful, and you're wondering if it's marketing bullshit or a real architectural answer.

Spoiler: MACH is not a silver bullet, but it's a solid approach when you've exceeded the limits of the monolith and your organization can handle distributed complexity. We supported a luxury retail brand through this migration: ROI at 18 months instead of 36, time-to-market divided by 3 on new markets. We've also seen projects go sideways because no one managed the integration or because they over-split into 80 microservices.

This guide explains concretely what MACH changes, when to migrate, how to avoid pitfalls, and what we learned in the field.

MACH: The 4 pillars explained without marketing

MACH stands for Microservices, API-first, Cloud-native, Headless. Not a product, not a framework: a set of architectural principles to build modular platforms where each component is independent and connected to others through APIs.

Microservices

Each business capability (product catalog, pricing, cart, inventory) is an autonomous service with its own database. You can deploy, scale, and replace each service without touching the others. In practice, this means your search team can ship a new Algolia engine without waiting for the checkout team to finish their redesign.

The trap: going into "1 microservice per use case" mode and ending up with 80 services for 10 devs. We saw an e-commerce startup with 12 microservices to manage the cart. Result: 6 months to debug a promo calculation because the logic was scattered. Split by stable business domain, not by feature.

API-first

All interaction between services goes through documented and versioned APIs. You design the API before implementation, not after. This forces stable contract thinking, backward compatibility, and allows front/mobile/partner teams to work in parallel.

Concretely: OpenAPI 3.x for documentation, consumer-driven contracts for testing, and an API gateway (Kong, Apigee, AWS API Gateway) to handle auth, rate-limiting, and versioning. On our luxury project, we required that no backend PR be merged without an up-to-date OpenAPI spec. It slows things down at first, saves weeks of debugging later.

Cloud-native

Designed for the cloud: containers (Docker/Kubernetes), auto-scaling, resilience by design (retry, circuit breaker), native observability (structured logs, metrics, distributed traces). Not just "hosted on AWS": designed to exploit cloud elasticity and redundancy.

Watch out: cloud-native doesn't mean no vendor lock-in. Using Lambda, DynamoDB, and EventBridge is very cloud-native, and very AWS-only. Accept some lock-in on managed services (RDS, S3, SQS), it's saved infrastructure time; avoid it on business logic.

Headless

The backend exposes APIs, the frontend is decoupled. You can have 5 fronts (desktop web, mobile web, iOS, Android, in-store kiosks) consuming the same backend APIs. You change front-end frameworks (React → Next.js → whatever-comes-next) without touching the backend.

In e-commerce, this means replacing Magento/Salesforce Commerce Cloud with commercetools or Shopify Plus on the backend, and building the front in Next.js or Nuxt. The headless CMS (Contentful, Strapi) handles content, the commerce engine handles transactions, the front aggregates everything.

From MACH to composable commerce: the business promise

MACH describes the technical principles. Composable commerce is the business result: the ability to assemble the best component for each need (best-of-breed) and replace each one independently.

Concrete example at our luxury client: they were using Salesforce Commerce Cloud (all-in-one). Limitations: mediocre product search, rigid personalization, impossible to launch an APAC market without going through Salesforce Professional Services. In composable MACH, they have:

  • commercetools for the commerce engine (API-first, multi-tenant, multi-region)
  • Algolia for search and facets
  • Segment for customer data (CDP)
  • Contentful for editorial content and landing pages
  • Next.js for web fronts (SSR, i18n)
  • Braze for CRM activation (email/push campaigns)

Result: new market in 6 weeks instead of 6 months, recommendation engine replaced in 2 sprints, A/B tests on checkout funnel without backend release. The price to pay: 6 integrations to maintain instead of one monolithic platform, and a platform team of 4 people (SRE + data architect) to manage orchestration.

When to migrate from a monolith?

MACH is not always the right answer. If you're doing €5M GMV per year with 5 devs and a Symfony monolith that runs fine, stay with it. MACH brings operational complexity: distributed monitoring, API version management, multiple deployments, decentralized ownership. It makes sense when:

  • Velocity blocked: each release takes 3 months, teams step on each other, impossible to deliver in parallel.
  • Critical time-to-market: you need to launch 10 markets in 18 months, or test 5 customer journeys simultaneously.
  • Technical scalability: your monolith doesn't scale horizontally, or certain parts (search, checkout) have very different scaling needs.
  • Multi-team organization: you have 30+ devs and want to split by domain (product, customer, order) with clear ownership.
  • Business differentiation: you want to replace a component (pricing, recommendation, CMS) with a better tool without redoing everything.

Integration pitfalls (and how to avoid them)

The tech of each component is not the risk. commercetools, Algolia, Contentful: these are mature products. The risk is integration between components and data governance.

1. Explosion in number of integrations

With 6 components, you potentially have 15 point-to-point integrations (n×(n-1)/2). In practice, it's less because not everything talks to everything, but that's still 8-10 integrations to maintain. Each integration has its data model, format (REST, GraphQL, webhook), auth system, SLA.

How we handled it: a central event bus (AWS EventBridge in our case) for asynchronous integrations, and a BFF (Backend-for-Frontend) that aggregates synchronous APIs for the fronts. Components never talk directly to each other synchronously, except the BFF which orchestrates.

ts
// BFF Next.js: server-side aggregation export async function getServerSideProps(context) { const [product, inventory, content] = await Promise.all([ commercetools.getProduct(context.params.sku), inventoryService.getStock(context.params.sku), contentful.getProductContent(context.params.sku) ]); return { props: { product, inventory, content } }; }

2. Master data governance

Who owns customer data? Inventory? Price? If customer data is duplicated between commercetools, Segment, and Braze, which one is the source of truth? You must define from the start a data owner for each reference entity.

At our luxury client, we documented this in an ADR (Architecture Decision Record):

  • Customer: Segment is the source of truth (CDP), commercetools and Braze consume.
  • Product: commercetools is master, Algolia and Contentful replicate via webhook.
  • Inventory: external ERP, replicated to commercetools every 15 min, exposed via commercetools API.
  • Order: commercetools is master, events sent to ERP and data warehouse via EventBridge.

No governance = data drift in 6 months, and you'll spend your days debugging inconsistencies between systems.

3. Over-splitting into microservices

The classic trap: splitting too fine. One microservice for VAT calculation, one for promos, one for cart, one for shipping fees. Result: network latency multiplied by 10, debugging impossible ("promo not applying" → 6 services to investigate), and endless coordinated deployments.

Pragmatic rule: split by bounded context (DDD). One context = one business domain with a coherent data model, managed by one team. For a mid-market e-commerce, you should have between 5 and 10 services, not 50. Examples of contexts: Catalog, Cart & Checkout, Order Management, Customer, Inventory.

4. Distributed monitoring and observability

"Checkout is slow" in a monolith: you open New Relic, you see the SQL query that's dragging. "Checkout is slow" in MACH: is it the BFF? The commercetools API? The inventory calculation? Algolia rate-limiting? You need distributed tracing (OpenTelemetry, Datadog APM, AWS X-Ray) from day 1.

We set up OpenTelemetry with trace IDs propagated in all HTTP headers. Each user request generates a trace that crosses BFF → commercetools → inventory → Algolia. In case of latency, we immediately see which service is guilty. Cost: ~2 days/dev of initial setup, savings: dozens of debugging hours per month.

Migration strategy: no big bang

You never migrate a monolith to MACH in a big bang. You extract one capability at a time behind an API, route it through a reverse proxy, and progressively turn off the old code. Classic pattern: Strangler Fig.

  1. Identify the most isolated capability and the most painful one. At our client: product search (slow, no facets, impossible to A/B test).
  2. Put a reverse proxy in front of the monolith (Nginx, Cloudflare Workers, AWS ALB). Route /search to the new Algolia service, the rest to the old one.
  3. Sync data from the monolith to the new component (initial batch + incremental sync via CDC or events).
  4. Switch 10% of traffic to the new service, monitor, adjust. Then 50%, then 100%.
  5. Delete the old code from the monolith once the new service has been stable for 2-3 weeks.
  6. Repeat for the next capability: customer data, cart, checkout, etc.

On the luxury project, we started with search + customer CDP (Algolia + Segment) in parallel, because it was isolated from transactional logic. Quick ROI: personalized results, segmented CRM campaigns. That took 3 months. Then checkout (commercetools), then content management (Contentful). 18 months total to be full MACH on 3 markets.

Concrete case: luxury retail, 18-month ROI

Context: luxury retail brand, €120M online GMV, 8 markets (EU + APAC), 40 devs. Salesforce Commerce Cloud (SFCC) monolith: quarterly deployment, impossible to launch a market in less than 6 months, catastrophic product search (no faceted search, no ML).

Business objective: launch 4 new APAC markets in 12 months, increase conversion rate from 1.8% to 2.5%, reduce feature time-to-market from 12 weeks to 3 weeks.

Target architecture: commercetools (commerce engine), Algolia (search + recommendations), Segment (CDP), Contentful (CMS), Next.js (web front), Braze (CRM). AWS EventBridge event bus, Next.js BFF for aggregation, Kubernetes infrastructure on EKS.

Phasing:

  1. M0-M3: search migration (Algolia) + CDP (Segment), sync from SFCC. Reverse proxy to route /search to Algolia. Result: +15% click-through rate on search.
  2. M3-M9: checkout migration (commercetools) on 2 pilot markets (FR + UK). Next.js front in SSR. Bidirectional sync SFCC ↔ commercetools for 3 months (coexistence).
  3. M9-M12: CMS migration (Contentful), progressive shutdown of SFCC on FR/UK. 2 markets 100% MACH.
  4. M12-M18: rollout on 6 other markets (2 per quarter). Foundation reused, only i18n config changes.

Results at M18:

  • Time-to-market: new market in 6 weeks vs 6 months before (÷10).
  • Conversion rate: from 1.8% to 2.4% (+33%) thanks to Algolia search and Segment personalization.
  • Velocity: 15 releases/week vs 1/quarter. Deployment decoupled by service.
  • ROI: initial target 36 months, achieved at 18 months. Gain = incremental revenue (4 APAC markets) + improved conversion - migration cost.

Hidden cost: platform team of 4 people (2 SRE, 1 data architect, 1 backend lead) to manage integrations, monitoring, data governance. Without them, the project would have gone sideways.

Checklist before you start

Before starting a MACH migration, validate these points:

  • You have an exec sponsor who understands it will take 12-18 months and ROI is not immediate.
  • You have an SRE/platform team or the budget to build one. No MACH without integration ownership.
  • Your teams know how to do API-first: OpenAPI, versioning, contracts. If not, train them first.
  • You have defined data owners for each reference entity (customer, product, inventory, order).
  • You have an incremental migration strategy (Strangler Fig), not a big bang plan.
  • You have distributed monitoring (tracing, centralized logs, metrics) ready from the first service.
  • You have budgeted cloud and SaaS costs: commercetools + Algolia + Segment + Contentful adds up fast (€50-150k/year depending on traffic).

Next steps

MACH is not a buzzword: it's a solid architectural answer when you've exceeded the limits of the monolith and have the organization to handle complexity. The gains are real — time-to-market divided by 3, velocity multiplied by 10, ability to test quickly — but the integration and governance cost is underestimated by 90% of projects.

If you're considering a migration, start small: extract an isolated capability (search, CDP, CMS), validate that you know how to integrate and monitor in production, then industrialize. Don't underestimate the need for a platform team from the start. And if you have questions about a concrete case — stack choice, migration strategy, data governance — we've delivered this type of project multiple times, we know where the landmines are.

Working on something similar?

Talk to an architect