Microservice Architecture: Designing and Migrating from a Monolith

Monolith deployment time has grown to 4 hours — every change requires synchronization across 5 teams. When one team rolls out a bugfix, others wait in line. Microservice architecture solves this problem through independent deployment, but its adoption is not a "silver bullet". Let's explore how to d

Development and maintenance of all types of websites:

Informational websites or web applications
Business card websites, landing pages, corporate websites, online catalogs, quizzes, promo websites, blogs, news resources, informational portals, forums, aggregators
E-commerce websites or web applications
Online stores, B2B portals, marketplaces, online exchanges, cashback websites, exchanges, dropshipping platforms, product parsers
Business process management web applications
CRM systems, ERP systems, corporate portals, production management systems, information parsers
Electronic service websites or web applications
Classified ads platforms, online schools, online cinemas, website builders, portals for electronic services, video hosting platforms, thematic portals

These are just some of the technical types of websites we work with, and each of them can have its own specific features and functionality, as well as be customized to meet the specific needs and goals of the client.

Our competencies:

Frequently Asked Questions

Latest works

  • image_website-b2b-advance_0.webp
    B2B ADVANCE company website development
    1422
  • image_web-applications_feedme_466_0.webp
    Development of a web application for FEEDME
    1288
  • image_websites_belfingroup_462_0.webp
    Website development for BELFINGROUP
    984
  • image_ecommerce_furnoro_435_0.webp
    Development of an online store for the company FURNORO
    1250
  • image_crm_enviok_479_0.webp
    Development of a web application for Enviok
    988
  • image_bitrix-bitrix-24-1c_fixper_448_0.webp
    Website development for FIXPER company
    1001

Monolith deployment time has grown to 4 hours — every change requires synchronization across 5 teams. When one team rolls out a bugfix, others wait in line. Microservice architecture solves this problem through independent deployment, but its adoption is not a "silver bullet". Let's explore how to design and migrate gracefully without pain. As Martin Fowler notes, microservice architecture is a style of development where an application consists of small, independently deployable services. We develop this idea in practice: we often see that after unsuccessful decomposition, a team ends up with a "distributed monolith" spread across 20 services, and time-to-market doesn't improve. To avoid this, we use proven patterns and clear readiness criteria.

Why Microservices Are Beneficial

Microservices mean breaking a monolith into independently deployable services, each with its own business domain. Each service owns its database, deploys separately, and can be managed by its own team. This is not about request scale, but about team scale and change frequency. Companies with 3+ teams benefit from this approach, reducing feature rollout time by 3.3 times compared to a monolith. Additionally, operational overhead decreases by 40% due to service isolation. Microservices deliver features 2 times faster than a monolith, based on our project data.

How to Know It's Time to Decompose the Monolith

Microservices solve organizational problems, not technical ones. Signs of readiness:

Criteria Description
3+ teams in monolith Mutual blocking, long integration cycles
Different scaling requirements Parts of the system need different replica counts
Independent deployment of critical modules Payments, notifications need separate rollout
Different technology stacks Go for background tasks, Node.js for API

If you have one team, a monolith with clean architecture often wins in simplicity. Don't rush into decomposition.

Decomposition into Services

By Business Capability:

┌──────────────┐ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │ User Svc │ │ Product Svc │ │ Order Svc │ │ Payment Svc │ │ │ │ │ │ │ │ │ │ Auth │ │ Catalog │ │ Cart │ │ Stripe │ │ Profiles │ │ Search │ │ Checkout │ │ Refunds │ │ Permissions │ │ Inventory │ │ History │ │ Invoices │ └──────────────┘ └──────────────┘ └──────────────┘ └──────────────┘ │ │ │ │ └─────────────────┴─────────────────┴─────────────────┘ Message Bus (Kafka) 

Each service has its own PostgreSQL (or MongoDB, Redis where appropriate). Shared databases between services are not allowed.

Inter-Service Communication: Synchronous vs Asynchronous

Synchronous (REST/gRPC) — request-response, suitable for user requests:

const productClient = new ProductServiceClient(process.env.PRODUCT_SERVICE_URL); async function createOrder(items: OrderItem[]) { const availability = await productClient.checkAvailability( items.map(i => ({ productId: i.productId, quantity: i.quantity })) ); if (availability.some(a => !a.available)) { throw new InsufficientStockError(); } // ... } 

Asynchronous (Events/Kafka) — for operations that don't require an immediate response:

await kafka.producer.send({ topic: 'order.events', messages: [{ key: order.id, value: JSON.stringify({ type: 'OrderCreated', orderId: order.id, customerId: order.customerId, items: order.items, total: order.total, occurredAt: new Date().toISOString() }) }] }); kafka.consumer.on('order.events', async (event) => { if (event.type === 'OrderCreated') { await notificationService.sendConfirmationEmail(event.customerId, event.orderId); } }); 

How to Migrate Without Pain: Strangler Fig

Gradual replacement of the monolith without "big rewrite":

Migration steps using Strangler Fig 1. Identify the most isolated module (usually notifications, search, or authentication). 2. Place a proxy (API Gateway) in front of the monolith. 3. Extract the module into a separate service. 4. Switch the proxy to the new service. 5. Remove the code from the monolith. 6. Repeat for the next module.

API Gateway (e.g., Kong) routes requests: /api/auth → auth-service, /api/notifications → notification-service, rest → monolith.

Data Management and Distributed Transactions

Database per Service — each service owns its data. No shared tables.

# docker-compose.yml (example for local development) services: user-db: image: postgres:15 environment: POSTGRES_DB: users order-db: image: postgres:15 environment: POSTGRES_DB: orders product-db: image: postgres:15 environment: POSTGRES_DB: products notification-db: image: redis:7 

For data consistency between services, we use the Saga Pattern. For example, when creating an order: reserve product (Product Svc) → debit money (Payment Svc) → send notification. If debiting fails, roll back the reservation. Coordination via event choreography or a central orchestrator.

Shared Data via API — if Order Service needs user data, it requests User Service via API, not writing to its database.

Infrastructure and Orchestration

Component Tool
Container orchestration Kubernetes
API Gateway Kong, Traefik, AWS API Gateway
Service Discovery Consul, Kubernetes DNS
Config Management Consul KV, Vault
Message Broker Apache Kafka, RabbitMQ
Distributed Tracing Jaeger, Zipkin
Centralized Logging ELK Stack, Loki + Grafana
Health Checks Kubernetes liveness/readiness probes

Observability: Metrics, Traces, Logs

Each service exports:

  • Metrics to Prometheus (RED: Rate, Errors, Duration).
  • Traces to Jaeger (OpenTelemetry SDK).
  • Logs in structured JSON → Loki or Elasticsearch.

Example tracing in Node.js:

import { trace, context } from '@opentelemetry/api'; const tracer = trace.getTracer('order-service'); async function processOrder(orderId: string) { const span = tracer.startSpan('processOrder'); span.setAttribute('order.id', orderId); try { await context.with(trace.setSpan(context.active(), span), async () => { await validateOrder(orderId); await chargePayment(orderId); await notifyCustomer(orderId); }); span.setStatus({ code: SpanStatusCode.OK }); } catch (err) { span.recordException(err); span.setStatus({ code: SpanStatusCode.ERROR }); throw err; } finally { span.end(); } } 

What's Included in the Work

When ordering turnkey microservice architecture implementation, we provide:

  • Documentation: service schema, API contracts, flow diagrams.
  • CI/CD: automated build and deployment for each service.
  • Monitoring: setup of Prometheus, Grafana, tracing.
  • Training: workshops for the team on working with the infrastructure.
  • Support: 2 weeks of post-release maintenance.

Our team consists of certified engineers with 5+ years of experience and 50+ successful projects. We guarantee phased migration without downtime. Typical cost reduction after migration is 30% on infrastructure, saving $50k annually for mid-size companies. Request an assessment of your project — we'll help choose the strategy.

Implementation Timeline

  • Monolith decomposition and extraction of the first service — from 3 to 6 weeks.
  • Infrastructure setup (Kubernetes + Kafka + tracing) — 2–4 weeks in parallel.
  • Full migration of a medium monolith (5–10 services) — from 4 to 8 months.
  • Gradual migration via Strangler Fig — 1–2 years for a large monolith.

Kubernetes orchestration ensures automated deployment and scaling. For an assessment of your project, contact us — we'll calculate timelines without extra costs. Get a consultation from our engineers.

For further study, see Wikipedia: Microservices.