Kokil Thapa - Professional Web Developer in Nepal
Freelancer Web Developer in Nepal with 15+ Years of Experience

Kokil Thapa is an experienced full-stack web developer focused on building fast, secure, and scalable web applications. He helps businesses and individuals create SEO-friendly, user-focused digital platforms designed for long-term growth.

Microservices vs Monolith: When to Split

By Kokil Thapa | Last reviewed: September 2026

Most teams ask about Microservices vs Monolith: When to Split after the first painful release cycle, not before launch. A single Laravel or Symfony codebase ships faster at the start. Later, one slow module, one risky deploy, or one overloaded queue makes everyone want separate services tomorrow. The honest answer is narrower than conference talks suggest. Split when organisational and operational pain clearly outweighs the cost of distributed systems—not when the architecture diagram looks outdated. This guide walks through the signals, trade-offs, and first safe steps I've used on production applications since 2010, including enterprise application builds in Nepal and international client work.

What is the difference between a monolith and microservices?

A monolith is one deployable application. All modules share a process, a database connection pool, and usually one release pipeline. A Laravel 12 or 13 app with controllers, jobs, and Blade views in one repository is a classic monolith. Microservices split the system into many small services. Each service owns its data, deploys independently, and talks over HTTP, gRPC, or message queues.

The comparison is not "old vs modern." Netflix-scale microservices solve Netflix-scale problems. A law-firm portal or florist eCommerce site often runs perfectly as a well-structured monolith for years. What matters is fit, not fashion.

Monolith vs Microservices TopologyMonolithWeb + API + JobsShared MySQL DBOne Deploy PipelineSingle repo, one releaseMicroservicesOrdersCatalogPaymentsAPI Gateway / Message BusDB ADB BDB CMany repos, many deploys
Microservices vs monolith topology: one deployable unit compared with independently scaled services and separate data stores.
CriteriaMonolithMicroservicesModular monolith (middle path)
Initial delivery speedFastSlowFast
Operational overheadLowHighLow to medium
Independent scalingLimitedStrongPartial via queues
Team autonomyShared codebasePer-service ownershipModule boundaries in one repo
Debugging complexityLowHigh without tracingLow
Best fitSmall teams, early productMany teams, clear domainsGrowing product, not ready to split

For many PHP teams, the modular monolith with Laravel is the underused option. You enforce boundaries inside one app before you pay the network tax. I've shipped booking systems and legal portals this way. They stayed monoliths for years because the business needed features, not infrastructure theatre.

When should you split a monolith into microservices?

Split when you can name a bounded context that hurts the rest of the system. Generic reasons like "the repo is big" or "we want to use Go" are weak signals. Strong signals are repeatable and measurable.

  • Independent scaling: One module—PDF generation, image processing, search—consumes most CPU while the rest of the app is idle.
  • Different release cadence: Marketing wants daily catalog changes but compliance blocks more than monthly payment updates.
  • Team ownership conflict: Three squads constantly break each other's migrations in one database schema.
  • Technology mismatch: A workload genuinely needs another runtime, for example heavy ML inference—not because developers prefer a new stack.
  • Fault isolation: A bug in notifications must not take checkout offline during peak sales.
  • Regulatory boundary: Payment or health data must sit in a separately audited service with stricter access controls.

If none of those apply, improve the monolith first. Extract slow queries, add Redis 8.10 caching, split queues, and tighten module boundaries. That work pays off even if you split later.

When to Split: Decision FlowClear domain boundary?YesOwn data + API contract?CI/CD per service ready?Observability + on-call?Split this boundaryStart with one serviceNo at any stepKeep modular monolithNo
Decision flow for Microservices vs Monolith: When to Split—each gate must pass before extracting a service.

On Adventure Third Pole Trek, a Laravel 12 + Livewire booking app, the whole system stayed a monolith. Trek inventory, supplier CRM, and customer checkout shared transactional data. Splitting early would have created distributed transactions without a clear win. Contrast that with a high-traffic catalog where read replicas and a separate search indexer eventually make sense.

How do you know your team is ready for microservices?

Microservices are an organisational pattern as much as a technical one. Martin Fowler and James Lewis described microservices as small autonomous services owned by small teams. If your "team" is two developers and one part-time sysadmin, you do not have microservices—you have micro-operations pain.

Before splitting, confirm you can answer yes to most of these operational questions.

  1. Can each service deploy without redeploying the entire platform?
  2. Do you have centralized logging, metrics, and distributed tracing?
  3. Can you roll back one service in under ten minutes?
  4. Do you have contract tests or schema versioning for service APIs?
  5. Is someone on call who understands more than one service?
  6. Can you reproduce production traffic in staging per service?

If you run Deployer 7 with GitLab CI on a single Ubuntu server—as I do on several sister legal-tech sites—you already have solid monolith deployment. That pipeline does not automatically become five pipelines with health checks, secrets rotation, and service discovery. Read the small-team reality check on microservices before you commit.

Teams under roughly eight engineers rarely benefit from more than one extracted service. Start with zero or one. Nepal agencies and SMB clients often have budget for Rs 15,000–40,000/month hosting (~USD 110–295), not a full platform engineering group. Match architecture to that reality.

Minimum platform checklist

You need a baseline before the first extraction. Without it, you will debug production blind.

# Example health endpoint every extracted service should expose
GET /health
{
  "status": "ok",
  "service": "payments",
  "version": "2026.03.1",
  "checks": {
    "database": "ok",
    "redis": "ok"
  }
}

Pair that with structured JSON logs, request IDs propagated across HTTP calls, and alerts on error rate—not only CPU graphs. The observability guide for microservices covers what to instrument first. If you cannot afford that tooling yet, stay monolithic and invest in testing and optimization instead.

What are the first safe steps to split a monolith?

Never rewrite the whole system in parallel. The strangler fig pattern wins in practice. You route traffic for one capability to a new service while the monolith handles everything else. Over months, the monolith shrinks.

Strangler Fig MigrationUsersReverseProxy / GatewayNew Servicee.g. NotificationsLegacy MonolithEverything elseRoute grows per feature until monolith is hollow
Strangler fig pattern: proxy traffic to a new microservice while the monolith still owns remaining domains.

A practical sequence for a Laravel monolith on PHP 8.3+ looks like this.

  1. Draw bounded contexts on paper—orders, catalog, billing, notifications—not folder names.
  2. Extract read-only APIs behind internal routes first. No database split yet.
  3. Move writes for one low-risk domain such as email or SMS dispatch.
  4. Give the new service its own database and sync with events, not shared tables.
  5. Delete duplicated code from the monolith only after traffic proves stable for weeks.

The full walkthrough lives in from monolith to microservices: a Laravel migration strategy. For API boundaries, follow Martin Fowler's microservices overview and design explicit contracts. Use OpenAPI documents stored in git. Validate payloads with JSON Schema in CI—a JSON formatter helps during contract reviews.

Anti-patterns that fail in production

I've seen these fail on client projects and rescued a few.

  • Distributed monolith: Separate repos but shared database tables and synchronous chains of six HTTP calls.
  • Big bang rewrite: Eighteen months of no business features while "the new architecture" cooks.
  • Chatty services: Order service calls inventory calls pricing calls tax on every cart click.
  • No idempotency: Payment webhooks retry and double-charge because only the monolith understood deduplication.

Payment flows on eCommerce builds like Quick And Easy Nepalese Grocery need idempotent callbacks whether they live in-module or in a separate service. Extract payments only when PCI scope or release isolation truly demands it.

How does Laravel fit into monolith vs microservices decisions in 2026?

Laravel 13.x targets PHP 8.3+. Laravel 12 remains supported to February 2027. Both are excellent monolith frameworks. Queues, Horizon, events, and Sanctum give you service-like isolation without network hops. Symfony 8.1 suits larger modular backends with stricter component boundaries.

When you do extract from Laravel, common first candidates include:

  • File and PDF processing — CPU-heavy, scales on workers separately.
  • Search indexing — Elasticsearch or Meilisearch consumers fed by domain events.
  • Notification delivery — SMS, email, push with third-party rate limits.
  • Reporting/analytics — read replicas and batch ETL without touching OLTP.

Keep core transactional logic—cart, booking, case intake—in the monolith until domain experts agree on consistency rules. Legal-tech portals such as Mijar Law Associates and Court Marriage In Nepal depend on document workflows tied to payments. Splitting document storage before you define retention and access policies creates compliance gaps.

For public APIs, API development standards matter more than service count. Version your REST endpoints, paginate consistently, and apply rate limits whether they sit behind one app or five. See the guide on API rate limiting and abuse prevention. Gateways are optional early; read API gateways for microservices when you have three or more external-facing services.

Operational Load: Before vs After SplitModular MonolithFive Microservices1 deploy pipeline1 app log stream1 DB backup planLow on-call surfaceFast local debugging5 pipelines + rollback playbooks5 log indexes + trace correlation5 DB backups + migration driftNetwork failures + partial outagesContract tests + schema versioningHigher hosting: Rs 25k+ / mo typicalIndependent scale where provenSplit only when ops capacity matches the right-side cost
Microservices vs monolith operational cost: five services multiply pipelines, logging, backups, and on-call work.

Reference the official Laravel queue documentation before reaching for Kafka. Often a dedicated queue worker group solves the scaling pain that tempted you toward microservices. MySQL 9.7 or PostgreSQL 18 with proper indexing still carries most SMB and mid-market loads inside one app.

When modular monolith beats premature microservices

Structure modules as if they could become services later. Use domain folders, internal interfaces, and events instead of direct model reach-across. Ban cross-module Eloquent queries in code review. That discipline costs little and preserves optionality.

app/
  Domain/
    Orders/
      Actions/PlaceOrder.php
      Events/OrderPlaced.php
      Models/Order.php
    Catalog/
      Actions/UpdateStock.php
      Listeners/ReserveStock.php

This layout appears in production Laravel apps I maintain. Nothing stops you from moving Orders into its own repo later—if the business case arrives. Until then, you ship features weekly instead of tuning service mesh config.

Planning helps. A short architecture review during planning and research beats a six-month detour into Kubernetes for a ten-user admin panel. For ongoing ops after a split, Linux system administration and support and maintenance contracts should reflect the new service count honestly.

Key Takeaways

  • Default to a modular monolith on Laravel 12/13 or Symfony until scaling, team, or compliance pain is concrete and repeated.
  • Split one bounded context at a time with the strangler fig pattern—never parallel full rewrites.
  • Require independent CI/CD, health checks, tracing, and on-call capacity before calling it microservices.
  • Extract notifications, search, or heavy workers first; keep money and core workflows in the monolith longer.
  • Measure operational cost in pipelines, backups, and incidents—not lines of code or developer preference.
  • Revisit the split decision every quarter; some "services" should merge back when complexity exceeds benefit.

People Also Ask

Is microservices always better than a monolith?

No. Microservices trade development simplicity for operational flexibility. Early-stage products and small teams almost always ship faster with a monolith. Microservices help when multiple teams need independent releases and you can fund platform engineering.

How big should a monolith be before splitting?

Line count is a poor metric. Split when a domain has clear boundaries, its own scaling profile, and repeated deploy conflicts—not when the repository hits an arbitrary size. Many successful monoliths exceed a million lines.

Can you use microservices with PHP and Laravel?

Yes. Each service can be a slim Lumen or Laravel app, or Symfony micro-kernel. The hard part is operations, not PHP. PHP 8.3+ with OPcache and proper queue workers handles substantial load per service.

What is the biggest mistake when moving to microservices?

Splitting before defining data ownership. Shared databases between "services" create distributed monoliths that are harder to debug than the original app. Give each service its own datastore and integrate with events or idempotent APIs.

Choose architecture for tomorrow's team, not yesterday's blog post

Microservices vs Monolith: When to Split is a business and operations question dressed as an architecture debate. Start monolithic, modular inside, and honest about your team's ops ceiling. Split the first service when metrics and incidents prove the boundary—not when a diagram looks crowded. If you want a second opinion on an existing Laravel or Symfony codebase, review the portfolio of shipped systems or talk through boundaries during custom software development. When you are ready for a structured review, contact us with your current deploy pain points and team size—we can map a modular monolith path or a safe first extraction without a costly rewrite.

Frequently Asked Questions

A monolith is one deployable application sharing a process, database pool, and release pipeline. Microservices split into many small services, each owning its data and deploying independently over HTTP, gRPC, or queues.

Split when you can name a bounded context that repeatedly hurts the rest of the system. Strong signals include independent scaling needs for one module, different release cadences between domains, team ownership conflicts over shared schema migrations, a genuine technology mismatch such as heavy ML inference, fault isolation requirements, or regulatory boundaries for payment or health data. If none apply, improve the monolith first with query tuning, Redis 8.10 caching, queue separation, and tighter module boundaries before paying the network tax of distributed systems.

A modular monolith keeps one deployable unit but enforces domain boundaries inside the codebase using folders, internal interfaces, and events instead of cross-module model calls. For Laravel 12 or 13 teams, it delivers fast initial delivery with low operational overhead while preserving the option to extract services later. Structure modules as if they could become services, ban cross-module Eloquent queries in review, and ship features weekly instead of managing multiple pipelines, health checks, and service discovery before the business case is proven.

No. Microservices trade development simplicity for operational flexibility. Early-stage products and small teams ship faster with a monolith.

Microservices are an organisational pattern as much as a technical one. Before splitting, confirm you can deploy each service independently, run centralized logging with distributed tracing, roll back one service in under ten minutes, maintain contract tests or schema versioning, staff on-call across services, and reproduce production traffic per service in staging. Teams under roughly eight engineers rarely benefit from more than one extracted service. If you run Deployer 7 with GitLab CI on a single Ubuntu server, that solid monolith pipeline does not automatically become five pipelines with secrets rotation and service discovery.

The strangler fig pattern routes traffic for one capability to a new service while the monolith handles everything else, shrinking it over months instead of rewriting in parallel. For a Laravel monolith on PHP 8.3 or higher, draw bounded contexts on paper first, extract read-only APIs behind internal routes without splitting the database yet, then move writes for a low-risk domain such as email or SMS dispatch. Give the new service its own database and sync with events, not shared tables. Delete duplicated monolith code only after traffic proves stable for weeks.

Common first candidates are file and PDF processing because it is CPU-heavy and scales on separate workers, search indexing fed by domain events into Elasticsearch or Meilisearch, notification delivery for SMS and email with third-party rate limits, and reporting or analytics using read replicas and batch ETL without touching OLTP. Keep core transactional logic such as cart, booking, and case intake in the monolith until domain experts agree on consistency rules. On legal-tech portals, splitting document storage before defining retention and access policies creates compliance gaps.

The worst failure mode is a distributed monolith: separate repos but shared database tables and long synchronous HTTP chains. Big bang rewrites that freeze business features for months while a new architecture cooks are equally destructive. Chatty services that call inventory, pricing, and tax on every cart click add latency without isolation benefits. Payment flows without idempotency double-charge when webhooks retry because only the monolith understood deduplication. Splitting before defining data ownership makes debugging harder than the original single codebase ever was.

Line count is a poor metric. Split when a domain has clear boundaries, its own scaling profile, and repeated deploy conflicts—not at an arbitrary repository size.

Yes. Each service can be a slim Lumen or Laravel app, or a Symfony micro-kernel. The hard part is operations, not PHP.

Five services multiply pipelines, logging, backups, and on-call work compared with a single deployable unit. Nepal agencies and SMB clients often budget Rs 15,000 to 40,000 per month for hosting, roughly USD 110 to 295, not a full platform engineering group. Measure cost in incident response, backup policies, and CI/CD maintenance per service, not lines of code. Linux administration and support contracts should honestly reflect the new service count. If you cannot fund observability tooling yet, stay monolithic and invest in testing and optimization instead.

When no strong split signals apply, extract slow queries, add Redis 8.10 caching, split queues, and tighten module boundaries inside the existing app. Laravel queues, Horizon, events, and Sanctum provide service-like isolation without network hops. MySQL 9.7 or PostgreSQL 18 with proper indexing still carries most SMB and mid-market loads inside one application. Reference the official Laravel queue documentation before reaching for Kafka. Often a dedicated queue worker group solves the scaling pain that tempted you toward microservices, and that modular discipline pays off even if you split later.

A distributed monolith looks like microservices on paper—separate repositories and deploy units—but services still share database tables and depend on synchronous chains of multiple HTTP calls for routine workflows. You inherit network latency, partial failure modes, and debugging complexity without gaining independent scaling or team autonomy. Data ownership stays blurred, so schema changes still require coordination across teams. In practice this is harder to operate than a well-structured monolith with clear module boundaries, which is why the article treats shared databases between services as a production anti-pattern to avoid from day one.

On Adventure Third Pole Trek, a Laravel 12 plus Livewire booking app, trek inventory, supplier CRM, and customer checkout shared transactional data, so the whole system stayed a monolith. Splitting early would have created distributed transactions without a clear win. Law-firm portals and florist eCommerce sites often run perfectly as well-structured monoliths for years because the business needed features, not infrastructure theatre. Default to a modular monolith on Laravel 12 or 13 or Symfony 8.1 until scaling, team, or compliance pain is concrete, repeated, and measurable—not when an architecture diagram looks crowded.

Before the first extraction, every service should expose a health endpoint reporting status, service name, version, and dependency checks such as database and Redis connectivity. Pair that with structured JSON logs, request IDs propagated across HTTP calls, and alerts on error rate rather than CPU graphs alone. Confirm centralized logging, metrics, and distributed tracing are in place. Without this baseline you debug production blind. Use OpenAPI documents stored in git and validate payloads with JSON Schema in CI for contract safety. If you cannot afford that tooling yet, remain monolithic and invest in testing and optimization instead.

Share this article

0 Comments

Leave a comment

Your email is not published. Comments appear once they have been read. Sign in to have your details filled in.

Quick Contact Options
Choose how you want to connect me: