When should ecommerce split a monolith into NestJS microservices?
Short answer: do not split an ecommerce monolith because microservices sound modern. Split when order management, payments, stock reservation, ERP or document generation start blocking checkout, release cadence or scaling. The safest first step is a strangler around orders: NestJS as the order service, PostgreSQL as its transactional model, RabbitMQ/Redis/Kafka for side effects and a clear rollback plan.
First, the uncomfortable truth: microservices do not fix a weak domain model
The most expensive mistake in ecommerce modernization is not always keeping a monolith too long. More often, the mistake is splitting a system before anyone understands it well enough. Then one difficult deployment becomes several difficult deployments, plus queues, retries, contract versioning, monitoring and new failure modes.
That is why a serious article about microservices has to start with "why?", not "which broker?". If checkout works, the team releases quickly and the main problem is messy code, start with a modular monolith, tests and domain boundaries. NestJS is useful there too because modules, dependency injection and TypeScript help structure a backend without immediately distributing it.
A microservice starts making sense when one area has different requirements from the rest of the application: order management must survive traffic peaks, payments need dedicated retries and idempotency, ERP slows checkout, PDF documents block resources, and every catalogue release requires full order regression. At that point you are not "rewriting the monolith as microservices". You are extracting one business-critical flow.
Signals that order management should be extracted first
In ecommerce, the first extraction candidate is rarely a generic user service or product service. It is usually the order flow because it touches revenue, stock, payments, invoicing, email, returns, CRM and ERP. When a side failure in that flow kills sales, the cost of distributed architecture starts to make commercial sense.
The strongest signal is a side-effect failure blocking checkout: a slow invoice generator, delayed ERP API, email outage or overloaded promotions module. The second signal is uneven scaling: cart and orders need more CPU, queueing and observability than the rest of the application. The third signal is release risk: the team is afraid to ship a catalogue change because it may affect payments.
The fourth signal is organizational: the order flow has a business owner, dedicated KPIs and its own backlog. If Head of Ecommerce, operations and finance meet every week around order defects, you have a domain. If the only complaint is "the code is ugly", you do not have one yet.
- Checkout synchronously depends on ERP, PDF, email or warehouse systems.
- Only the order area fails during peaks, but the whole monolith must be scaled.
- Changes to promotions, payments or invoices require full-platform regression.
- Order defects have measurable cost: lost payments, manual fixes, complaints and delayed shipments.
When to keep the monolith
Martin Fowler described the Monolith First principle: many successful microservice stories started with a monolith that grew and was broken up, while many systems started as microservices from scratch ended in serious trouble. This is not anti-microservices. It is a warning against paying the microservice premium before the company has stable domain boundaries and operational maturity.
Keep the monolith if you have a small team, low order volume, few integrations, simple checkout and no real pressure for independent deployments. In that setup, improve the monolith first: extract NestJS modules, clean up transactions, add contract tests around integrations, move side effects into queues and improve observability.
This is often the most valuable DDT finding: we do not design five services immediately; we determine whether the problem is domain complexity, performance, organization or code quality. Sometimes a client needs two sprints of checkout hardening, not a six-month migration.
Why NestJS fits a safe extraction
The NestJS documentation defines a microservice as an application that uses a transport other than HTTP and supports both request-response and event-based messaging. That is practical in ecommerce migration because not every order step behaves the same way. Payment authorization may need a response. Email, CRM updates or PDF generation can be events.
NestJS gives a consistent model for modules, controllers, providers, validation, guards, interceptors and tests. As a result, the order service can be small without being chaotic. It can expose an API for checkout, consume events from the monolith, publish `order_paid`, own its database and have separate health checks, logs and tracing.
At GMI we often pair NestJS with PostgreSQL, Redis, RabbitMQ or Kafka, depending on the job. RabbitMQ is strong for classic work queues and acknowledgements. Redis can be enough for simpler queues and cache. Kafka makes sense when the event stream is a product in itself: many consumers, replay, audit and high volume.
Strangler Fig: do not rewrite, take over traffic slice by slice
Microsoft describes Strangler Fig as a modernization pattern where the new system gradually handles requests for a chosen area while legacy continues to serve the rest. This fits ecommerce because a big-bang checkout rewrite is too risky: one error in payment, stock or tax can stop sales.
The safest variant starts with a domain map and an adapter. The old monolith still handles most traffic, but the new order service takes a narrow case: for example online orders for one country, one payment method or one B2B channel. Only after comparing data, logs, payments and complaints does the scope grow.
Rollback must be real. If the new order service fails, routing should allow unopened checkouts to return to the old path. For orders already in progress you need idempotency keys, event correlation and clear status: accepted, paid, waiting for ERP, integration failed, cancelled.
Reference architecture for an extracted order service
A practical model looks like this: a Next.js or React Native frontend sends checkout to an API gateway or backend-for-frontend. The new NestJS order service validates the cart, stores order intent in PostgreSQL and publishes events. The broker distributes side work: invoice, email, CRM update, ERP sync, app push and operational reporting.
The monolith does not disappear on day one. It may still own catalogue, customer accounts or parts of the admin panel. The difference is that the critical path "accept the order and do not lose money" has its own data model, tests, monitoring and scalability.
The key rule is simple: side effects must not block order acceptance unless they are part of a business decision. Payment, stock reservation and price validation may be critical. PDF, email, CRM and many ERP operations can usually be asynchronous with retry, dead-letter queue and alerting.
Testing, observability and production conditions
Microservices without observability are worse than a monolith because the problem disappears from one stack trace and spreads across the network. The minimum standard is request correlation, structured logs, queue metrics, event processing time, retry count, dead-letter queue, checkout dashboard and business alerts: conversion drop, payment errors, delayed ERP orders.
Tests must cover contracts, not only functions. Checkout needs tests for idempotency, double click, payment timeout, slow ERP, document generation failure and event reprocessing. Consumer-driven contracts are often more useful than huge end-to-end tests that fail randomly and explain nothing.
In DDT we also define operational ownership: who reacts to an alert, who can manually repair an order, when we replay an event, when we cancel, and when we escalate to finance or warehouse. Without those decisions, the architecture looks good on a diagram but does not help on Monday at 8:30.
Cost and scope: what you are actually buying
Extracting one critical ecommerce area into NestJS usually sits in a broad PLN 160,000-300,000 range, but the number is not very useful without DDT. Cost depends on monolith quality, number of integrations, reporting requirements, order volume, historical data, test level and whether ERP allows safe synchronization.
The smallest useful scope is often: domain map, order service, owned database, monolith adapter, broker, basic workers, error dashboard and checkout regression scenarios. More expensive scopes include multi-country, B2B approval flows, split shipments, trade credit, full event sourcing, advanced replay and migration of historical orders.
GMI should not promise fixed price before discovery. We promise a fast consultation and initial estimate within 48 hours, then fixed price after DDT when the actual risks are known. This matters in monoliths because the most expensive surprises usually live in old integrations, manual exceptions and undocumented data.
Checklist before splitting the monolith
The checklist below is a good agenda for CTO, ecommerce, finance and operations. If most answers are unknown, do not start by coding a microservice. Start with DDT and instrumentation of the current system.
- Which checkout step creates the most errors or delay?
- Which integrations must be synchronous, and which can run through events?
- Do we have idempotency keys for payments and orders?
- Can we compare old and new paths on the same data?
- What is rollback for new checkouts and for orders in progress?
- Who operationally owns the dead-letter queue and manual repairs?
- Which business metrics prove the extraction works: conversion, payment success, order latency, ERP sync delay?
How GMI runs this kind of project
We start with DDT: mapping the order process, integrations, data, operational exceptions and production risks. Then we propose the narrowest slice that removes a real constraint: for example PDF and ERP outside checkout, a separate order service, or first a modular monolith with a side-effect queue.
Technically, we usually work in TypeScript: NestJS for backend, PostgreSQL for transactional data, Redis/RabbitMQ/Kafka for queues, Next.js or React Native for frontends, and MedusaJS where a headless commerce core makes sense. But technology is the result of a domain decision, not the starting point.
Commercially, the project must give the client control: source-code ownership, no vendor lock-in, fixed price after DDT, test scenarios and a clear maintenance model. An order microservice succeeds only when it works beyond the demo and reduces fear around Black Friday, ERP integration and the next checkout release.
Sources and further reading
NestJS Microservices overview: https://docs.nestjs.com/microservices/basics
NestJS RabbitMQ transporter: https://docs.nestjs.com/microservices/rabbitmq
Martin Fowler, Monolith First: https://martinfowler.com/bliki/MonolithFirst.html
Microsoft Azure Architecture Center, Strangler Fig Pattern: https://learn.microsoft.com/en-us/azure/architecture/patterns/strangler-fig
From Monolith to Microservices: A Classification of Refactoring Approaches: https://arxiv.org/abs/1807.10059
From Monolith to Microservices: A Comparative Evaluation of Decomposition Frameworks: https://arxiv.org/abs/2601.23141
GMI guide to event-driven commerce with Redis, RabbitMQ and SQS: /blog/event-driven-commerce-redis-rabbitmq-sqs
GMI guide to NestJS, Prisma and PostgreSQL at scale: /blog/nestjs-prisma-postgresql-at-scale
Frequently asked questions
- When should ecommerce split a monolith into microservices?
- When a specific domain has different requirements from the rest of the application: checkout fails because of side effects, order management needs separate scaling, ERP integrations block sales or release risk slows the team. Do not split only because monolith code is messy.
- Why does the first extraction usually start with order management?
- Because orders touch revenue, payments, stock, invoices, email, ERP and customer service. If that flow is slow or fragile, the company feels the cost immediately: lost payments, manual fixes, delayed shipments and fear around checkout releases.
- Is NestJS a good choice for ecommerce microservices?
- Yes, if the team works in TypeScript and needs a structured backend with modules, tests, validation and microservice transports. NestJS does not solve domain boundaries by itself, but it provides a stable foundation for order services, workers and integrations.
- How much does extracting an order service to NestJS cost?
- A typical scope for one critical ecommerce area is roughly PLN 160,000-300,000, but fixed price only makes sense after DDT. Cost depends on ERP/PIM/WMS integrations, monolith quality, order volume, data migration, testing and observability level.
- Do microservices create cloud vendor lock-in?
- They do not have to. NestJS in containers, PostgreSQL, RabbitMQ/Redis/Kafka and standard APIs can be designed for portability. Lock-in appears when business logic depends on closed services without adapters and an exit plan. At GMI, after paid milestones, the client owns the code.
- Is it better to rewrite the whole monolith at once?
- Usually no. Strangler Fig is safer: the new system takes over one chosen flow, legacy serves the rest, and the team compares data with a rollback path. A big-bang checkout rewrite is risky because one defect can stop sales.
Content updated: July 11, 2026