In short
Software architecture is the set of high-level structural decisions about a system - how it is split into parts, how those parts talk to each other, and which qualities (scalability, availability, maintainability) the split is meant to buy. A monolith deploys the whole application as one unit; microservices split it into many small, independently deployable services, each owning its data and communicating over the network. The choice governs everything downstream: deployment, database design, testing, team structure and failure behaviour. It is examined in Software Engineering and Distributed Systems papers (architectural styles, coupling and cohesion, quality attributes) and is almost guaranteed in system-design rounds at Indian employers - Flipkart, Swiggy, Zomato, Razorpay, PhonePe, Zerodha, Paytm, Ola, Infosys/TCS/Wipro digital units - because every large Indian consumer platform has lived through this migration.
Explained
What architecture is, and what it is judged by
- Software architecture = the structure of a system: its components, their responsibilities, their connectors (calls, queues, shared data), and the constraints and rationale behind the split.
- Distinguish from design: architecture decides *modules, boundaries and technologies* (hard to change later); low-level design decides *classes and methods* inside a module (cheap to change).
- Architecturally significant requirements are the non-functional / quality attributes, not features: performance, scalability, availability, security, maintainability, testability, deployability, portability, cost.
- 4+1 view model (Kruchten) - examined often: Logical (functionality/classes), Process (concurrency, runtime), Development (modules, build), Physical/Deployment (hardware, nodes), plus Scenarios/Use cases that tie the four together.
- Coupling (dependency between modules - keep low) and cohesion (relatedness within a module - keep high) are the measuring sticks for any split. A good boundary has high cohesion inside and a thin, stable interface outside.
- Conway's Law: a system's structure mirrors the communication structure of the organisation that builds it. Microservices usually require reorganising teams first ("inverse Conway manoeuvre").
- Architectural styles you should be able to name: layered (n-tier), client-server, monolithic, modular monolith, service-oriented (SOA), microservices, event-driven (pub/sub), pipe-and-filter, repository/blackboard, peer-to-peer, microkernel/plug-in, serverless (FaaS), space-based.
The monolith
- Definition: one codebase, one build artefact (a single WAR/JAR, one Django/Rails app, one PHP deployment), one process type, usually one shared database. Internal structure is normally layered: presentation → application/business logic → data access → database.
- Types:
- Single-tier / big ball of mud: no enforced internal boundaries; modules call anything.
- Layered monolith: strict layer rules (a layer talks only to the one below).
- Modular monolith: enforced module boundaries, separate schemas per module, in-process calls only. Often the correct answer in an interview - monolith simplicity with microservice-like boundaries.
- Advantages: simple to develop, build, test and deploy; one repository and one CI pipeline; in-process calls are nanoseconds, not milliseconds; ACID transactions across the whole domain (single database, single commit); easy end-to-end debugging with one stack trace; low infrastructure cost; refactoring across module lines is a compiler-checked change.
- Limitations:
- Scaling is all-or-nothing - to scale a hot module you replicate the whole application, including idle code and its memory.
- Deployment coupling: one line of risky code blocks every team's release; long build/test cycles; one unhandled memory leak can take the entire application down.
- Technology lock-in: one language/runtime/framework version for everything.
- Codebase gravity: as it grows, onboarding slows, IDE/build times grow, and module boundaries erode unless actively policed.
- Large teams contend on the same code - merge conflicts and release-train queuing.
Microservices
- Definition: an application built as a suite of small services, each (a) organised around a business capability, (b) independently deployable, (c) owning its own data store, (d) communicating over lightweight network protocols (HTTP/REST, gRPC, messaging), (e) owned end-to-end by one small team.
- Core principles:
- Single responsibility / bounded context - from Domain-Driven Design; a service maps to one bounded context (Orders, Payments, Catalogue, Notification), not to a technical layer.
- Database per service - no other service reads your tables; data is exposed only through your API. This is the hardest and most important rule.
- Decentralised governance - each team picks its own stack ("polyglot programming", "polyglot persistence").
- Design for failure - the network is unreliable; every remote call must have a timeout, a retry policy and a fallback.
- Smart endpoints, dumb pipes - logic in services, not in the messaging middleware (the opposite of classic SOA/ESB).
- Supporting components (name these in exams):
- API gateway - single entry point for clients: routing, authentication, rate limiting, request aggregation, TLS termination (Kong, NGINX, AWS API Gateway, Spring Cloud Gateway).
- Service registry and discovery - services register (Eureka, Consul, etcd) so callers find live instances without hardcoded IPs; Kubernetes does this through Services and DNS.
- Load balancer - server-side (NGINX, ELB) or client-side (Ribbon/Spring Cloud LoadBalancer).
- Configuration server - externalised config (Spring Cloud Config, ConfigMaps).
- Message broker / event bus - Kafka, RabbitMQ, AWS SQS/SNS for asynchronous communication.
- Containers and orchestration - Docker images, Kubernetes for scheduling, scaling, health checks, rolling deployments.
- Observability - centralised logging (ELK/Loki), metrics (Prometheus + Grafana), distributed tracing with a correlation/trace ID propagated through every hop (Jaeger, Zipkin, OpenTelemetry).
- Service mesh (Istio, Linkerd) - sidecar proxies handle retries, mTLS, traffic splitting outside application code.
- Advantages: independent deployment and scaling per service; fault isolation; small, autonomous teams; technology freedom; faster onboarding on a small codebase; targeted scaling is cheaper for skewed loads.
- Limitations: distributed-system complexity; no cross-service ACID transaction; network latency and partial failure; hard integration testing; operational burden (CI/CD, monitoring, on-call per service); data duplication and eventual consistency; versioning of APIs; much harder to trace a bug across 15 hops; higher baseline infrastructure cost.
Communication, data and distributed-data patterns
- Synchronous (REST over HTTP, gRPC): simple request-reply, immediate answer, but the caller is blocked and coupled to the callee's availability. Latency adds up in a chain (latency amplification).
- Asynchronous (events/messages via Kafka or RabbitMQ): publisher does not wait, consumers scale independently, the system survives a consumer being down; but harder to reason about, needs idempotent consumers and ordering guarantees.
- Orchestration vs choreography: a central orchestrator drives the steps (easy to see, single point of coupling) versus services reacting to each other's events (loosely coupled, harder to trace).
- CAP theorem: in a network partition a distributed data store can keep only Consistency or Availability, not both - most microservice data stores choose AP with eventual consistency. PACELC extends it: else (no partition) choose between Latency and Consistency.
- Saga pattern - a business transaction spanning services, implemented as a sequence of local transactions, each with a compensating transaction to undo it. Two flavours: choreographed (events) and orchestrated (a saga coordinator). Example: Order created → Payment captured → Inventory reserved; if inventory fails, refund the payment.
- Two-phase commit (2PC) gives atomicity but blocks and scales poorly - avoided in microservices.
- Transactional outbox + CDC: write the business row and an outbox row in one local transaction, then publish from the outbox (Debezium) - fixes the "DB committed but event lost" dual-write problem.
- CQRS - separate the write model from one or more read models; often paired with event sourcing (store the sequence of events, derive state).
- API composition / BFF: an aggregator (or Backend-for-Frontend) assembles a screen from several services so the mobile app makes one call.
- Resilience patterns: timeouts, bounded retries with exponential backoff and jitter, circuit breaker (closed → open → half-open; Resilience4j/Hystrix), bulkhead (separate thread pools per dependency), rate limiting, graceful degradation, idempotency keys (essential for payment retries under UPI).
Choosing, and migrating
- Start monolithic ("monolith first") when the domain is not yet understood, the team is small (under roughly 8-10 engineers), time-to-market dominates, or the load is modest. Boundaries drawn wrong in a microservice are vastly costlier to move than in a monolith.
- Go microservices when: different modules need very different scaling; many teams are blocked on one release pipeline; parts need different technologies; availability requirements demand fault isolation; the domain is well understood and stable.
- Strangler fig pattern - the standard migration: put a façade/gateway in front of the monolith, extract one bounded context at a time, route that traffic to the new service, repeat until the monolith is gone. Extract the module that is most painful (highest change rate or highest scaling need) first.
- Supporting migration moves: branch by abstraction, anti-corruption layer between new service and legacy schema, database view/trigger-based decoupling, then split the schema.
- Anti-patterns:
- Distributed monolith - services that must be deployed together, share a database, or chain synchronously; all the cost of distribution with none of the benefit.
- Nanoservices - splits so fine that network overhead and operational cost dominate.
- Shared database across services - couples schemas and kills independent deployment.
- Entity services - a service per database table instead of per business capability.
- Microservices without automated CI/CD, monitoring and containerisation - "you must be this tall to use microservices".
- Documenting decisions: ADR (Architecture Decision Record) - one short file per decision (context, decision, consequences), kept in the repo. C4 model diagrams (Context, Container, Component, Code). ISO/IEC/IEEE 42010 is the standard on architecture description; ISO/IEC 25010 defines the quality-attribute vocabulary (functional suitability, performance efficiency, compatibility, usability, reliability, security, maintainability, portability).
Indian context, compliance and practice
- Data residency: the RBI storage of payment system data directive (April 2018) requires payment system data of Indian transactions to be stored only in India - this forces data-store placement decisions in payment microservices. The Digital Personal Data Protection Act, 2023 governs personal-data processing and consent; rules and phased enforcement have been rolling out, so check the current notified position before quoting specifics.
- CERT-In directions (2022) require specified logs to be retained (reported as 180 days, within India) and certain incidents to be reported within 6 hours - centralised logging in a microservice estate is a compliance requirement, not just an engineering nicety.
- Volume reality that drives these designs: UPI processes on the order of 18-20 billion transactions a month in 2025-26 (NPCI publishes the monthly figure; it keeps rising) - the kind of skewed, spiky, high-availability load that pushes payment platforms to independently scalable services.
- Typical Indian stacks: Java/Spring Boot microservices (banks, BFSI, Infosys/TCS modernisation projects), Go/Node.js (consumer startups), Python/Django monoliths, Kafka for events, Kubernetes on AWS/Azure/GCP, and public-sector platforms (Aadhaar authentication, GSTN, DigiLocker, ONDC, Account Aggregator) built as API-first services.
Key points
- Software architecture - the high-level component/connector structure plus the rationale; driven by non-functional requirements.
- Monolith - single codebase, single deployable, usually one shared database; simplest correct default for small systems.
- Modular monolith - enforced internal boundaries without network calls; the pragmatic middle path.
- Microservice - small, independently deployable service around a business capability, owning its data.
- Database per service - the defining rule; sharing a database makes it a distributed monolith.
- Bounded context - DDD unit that gives the right service boundary; one service per capability, not per table.
- API gateway - single client entry point doing routing, auth, rate limiting and aggregation.
- Service discovery - dynamic registry (Eureka/Consul/Kubernetes DNS) replacing hardcoded endpoints.
- CAP theorem - under partition, choose consistency or availability; microservice data usually chooses availability with eventual consistency.
- Saga - distributed transaction as local transactions plus compensating actions, replacing 2PC.
- CQRS and event sourcing - split read and write models; derive state from stored events.
- Circuit breaker - stop calling a failing dependency (open), probe later (half-open) to avoid cascading failure.
- Idempotency - the same request applied twice has the same effect; mandatory with retries and at-least-once messaging.
- Strangler fig - migrate by extracting one context at a time behind a façade, never a big-bang rewrite.
- Conway's Law - architecture mirrors team communication structure; restructure teams with the system.
- Distributed monolith - the chief anti-pattern: all the cost of distribution, none of the independence.
- Observability - centralised logs, metrics and distributed tracing with a propagated correlation ID.
- Deployment unit count - the single clearest exam discriminator: monolith = 1, microservices = N independently releasable units.
Formulas and examples
Availability with R redundant instances (independent failures): A = 1 − (1 − Aᵢ)R
Downtime per year = (1 − A) × 8,760 h; per month = (1 − A) × 730 h
Latency of a synchronous chain: L_total = Σ Lᵢ + Σ (network RTT per hop); parallel fan-out: L = max(Lᵢ) + overhead
Little's Law: L = λ × W (L = concurrent requests in system, λ = arrival rate in req/s, W = mean response time in s)
Instances needed: N = ceil(λ × W / c) = ceil(λ / (c/W)), where c = concurrent requests one instance handles
Utilisation and queueing (M/M/1): ρ = λ/μ; W = 1/(μ − λ) (μ = service rate, req/s; valid only for ρ < 1)
Cost comparison: Cost = Σ (instances_i × size_i × rate per unit per hour × hours)
Example 1 - availability of a chain versus redundancy. A checkout request passes through gateway → order → payment → inventory, each 99.9% available (A = 0.999).
- A_chain = 0.999⁴ = 0.996006 ≈ 99.60%.
- Downtime = (1 − 0.996006) × 8,760 = 0.003994 × 8,760 ≈ 34.98 h/year - against 8.76 h for a single 99.9% monolith.
- Now run 2 independent instances of each service: per-service A = 1 − (0.001)² = 0.999999. Chain = 0.999999⁴ ≈ 0.999996 → downtime ≈ 0.000004 × 8,760 ≈ 0.035 h/year ≈ 2.1 minutes.
- Conclusion: splitting a system multiplies failure probabilities; microservices only improve availability when combined with redundancy and asynchronous decoupling.
Example 2 - targeted scaling saves money. A monolith runs on 20 instances at ₹8/hour each. Profiling shows the search module consumes 70% of CPU, everything else 30%.
- Monolith cost = 20 × 8 × 730 = ₹1,16,800 per month (730 h ≈ one month).
- After splitting: search needs 14 instances (70% of 20), the rest fits in 6 → the same 20, no gain until load shifts.
- Festival sale triples search traffic only. Microservices: search 14 × 3 = 42 plus 6 others = 48 instances → 48 × 8 × 730 = ₹2,80,320. Monolith: must scale *all* 20 by 3 to reach the same search capacity → 60 instances → 60 × 8 × 730 = ₹3,50,400.
- Saving = ₹3,50,400 − ₹2,80,320 = ₹70,080 per month (20%) - before subtracting the added cost of gateway, broker, monitoring and per-service CI, which for a small estate can exceed the saving.
Example 3 - sizing with Little's Law. An order service must serve λ = 1,200 req/s with mean response time W = 150 ms; one instance handles c = 60 concurrent requests.
- Concurrency in system L = λ × W = 1,200 × 0.15 = 180 concurrent requests.
- Instances = ceil(180/60) = 3; with N+1 redundancy and headroom for a 2× spike, provision 6-8.
- If an added remote call pushes W to 250 ms: L = 1,200 × 0.25 = 300 → ceil(300/60) = 5 instances - a 67% capacity increase bought by one extra network hop. This is the quantified cost of chatty service design.
Example 4 - latency amplification. A mobile screen needs profile, orders, recommendations and offers. Each service takes 40 ms; network RTT is 10 ms per hop.
- Sequential from the client: 4 × (40 + 10) = 200 ms.
- Via an aggregator calling in parallel: 10 (client↔gateway RTT) + 10 (internal RTT) + max(40) = 60 ms.
- Chained services (A calls B calls C calls D): 40 + 10 + 40 + 10 + 40 + 10 + 40 = 190 ms, and availability falls as in Example 1 - which is why deep synchronous chains are an anti-pattern.
Example 5 - saga with compensation. Order ₹4,500: (1) Order service creates order PENDING; (2) Payment service debits ₹4,500; (3) Inventory service reserves stock - fails, out of stock.
- Compensation runs in reverse: refund ₹4,500 (compensating transaction for step 2), set order CANCELLED (step 1).
- Net effect: consistent, but only eventually - the customer may briefly see a debit and an order marked pending. The refund must carry an idempotency key so a retried refund does not pay twice.
| Dimension | Monolith | Microservices |
|---|---|---|
| Deployable units | 1 | N (one per service) |
| Database | Usually one shared schema | One per service |
| Transactions | ACID, single commit | Saga + eventual consistency |
| Inter-module call | In-process, ~nanoseconds | Network, ~0.5-50 ms |
| Scaling | Whole application | Per service |
| Technology | Single stack | Polyglot |
| Fault isolation | Poor (one crash, all down) | Good, if async and redundant |
| Testing | Easy end-to-end | Unit easy, integration hard (contract tests, Testcontainers) |
| Debugging | One stack trace | Distributed tracing needed |
| Team fit | 1 small team | Many autonomous teams |
| Infra and ops cost | Low | High (gateway, broker, orchestration, per-service CI/CD) |
| Best for | New products, modest load, small teams | Large skewed load, many teams, well-understood domain |
| Aspect | SOA | Microservices |
|---|---|---|
| Granularity | Coarse, enterprise-wide services | Fine, business-capability sized |
| Integration | ESB with orchestration logic | Smart endpoints, dumb pipes |
| Data | Often shared enterprise database | Database per service |
| Protocols | SOAP/WSDL, XML | REST/JSON, gRPC, messaging |
| Governance | Centralised | Decentralised per team |
Where it is used
- E-commerce and food delivery: Flipkart, Myntra, Swiggy, Zomato and BigBasket run catalogue, search, cart, pricing, order, delivery-tracking and notification as separate services - search and tracking need far more capacity than account management.
- Fintech and banking: Razorpay, PhonePe, Paytm, Zerodha and bank digital channels isolate payment, UPI handler, KYC, ledger and notification services; ledger and settlement often stay strongly consistent and monolithic by design, with RBI data-localisation shaping where stores live.
- Public digital infrastructure: Aadhaar authentication, UPI/NPCI, GSTN, DigiLocker, ONDC and Account Aggregator are built as versioned, independently scaled API services.
- IT services modernisation: TCS, Infosys, Wipro, HCLTech, Accenture and Capgemini sell legacy-to-microservices migration (mainframe or Java EE monolith → Spring Boot on Kubernetes) using the strangler fig pattern - a large share of fresher placements go into these projects.
- Job roles: backend engineer, software architect, solution architect, DevOps/SRE/platform engineer, cloud engineer; the system-design interview round for SDE-2 and above is almost entirely this topic.
- Products and tooling: Spring Boot/Spring Cloud, Docker, Kubernetes, Kafka, Kong/NGINX, Prometheus-Grafana, Jaeger/OpenTelemetry, Resilience4j, Istio - the standard toolchain names expected in interviews.
Interview questions
- Q: What is the single defining difference between a monolith and microservices? A: The number of independently deployable units - a monolith ships as one artefact, microservices ship and scale each service separately, each owning its own data store.
- Q: Would you start a new product with microservices? A: Usually no - start with a modular monolith to learn the domain, then extract services where scaling, team contention or availability demands it; wrong boundaries are far cheaper to move inside one codebase.
- Q: Why is "database per service" so strictly insisted upon? A: A shared schema couples services at the data layer, so no service can change its model or deploy independently - that is a distributed monolith with extra latency.
- Q: How do you maintain consistency without distributed transactions? A: With sagas: a sequence of local transactions, each with a compensating transaction to undo it, giving eventual rather than immediate consistency.
- Q: What does a circuit breaker do? A: After a threshold of failures it opens and fails calls to a sick dependency immediately, then half-opens to probe recovery - preventing thread-pool exhaustion and cascading failure.
- Q: Does splitting a system automatically improve availability? A: No - a synchronous chain multiplies availabilities, so four 99.9% services give about 99.6%; improvement comes from redundancy, asynchronous messaging and graceful degradation.
- Q: Synchronous REST or asynchronous events between services? A: REST/gRPC when the caller needs an immediate answer; events when the work can be deferred, must fan out to many consumers, or must survive the consumer being down.
- Q: What is a distributed monolith and how would you spot one? A: Services that must be released together, share a database, or form deep synchronous chains - the giveaway is that you cannot deploy one service without coordinating others.
- Q: How do you debug a request that crosses eight services? A: Propagate a correlation/trace ID through every hop and use distributed tracing (OpenTelemetry with Jaeger/Zipkin) plus centralised logs and per-service metrics.
- Q: How would you migrate a 10-year-old monolith? A: Strangler fig - put a gateway in front, extract the highest-pain bounded context first with an anti-corruption layer, split its data, route traffic, repeat; never a big-bang rewrite.
- Q: What does the API gateway do, and what is its risk? A: Routing, authentication, rate limiting, TLS termination and response aggregation; the risk is that it becomes a single point of failure and a dumping ground for business logic, so keep it thin and redundant.
- Q: Why must message consumers be idempotent? A: Brokers deliver at-least-once, so a duplicate must not debit twice - deduplicate on an idempotency key or message ID.
- Q: How small should a microservice be? A: Sized to a bounded context owned by one small team that can rewrite it in a few weeks - not one per table; lines of code is the wrong metric.
Common mistakes
- Calling any system with multiple servers or several APIs "microservices" when they all share one database and deploy together.
- Claiming microservices are "always better" or "faster" - they add network latency and operational cost, and only pay off at a certain scale and team size.
- Splitting by technical layer (UI service, business service, DAO service) or per table instead of by business capability.
- Forgetting that availabilities multiply along a synchronous chain, and quoting a per-service figure as the system figure.
- Assuming ACID transactions still work across services, then inventing a two-phase commit answer where a saga is expected.
- Ignoring the prerequisites - CI/CD, containerisation, centralised logging, tracing and on-call - and judging the architecture when the real failure was operational immaturity.
- In exams, listing advantages and disadvantages without quality attributes, coupling/cohesion or the 4+1 views that the marking scheme rewards.
Related topics
- SDLC and Agile · Design patterns · Low-level design (object-oriented design) interviews · Software testing basics · Operating systems and distributed systems · DBMS: transactions and concurrency control · Cloud computing and DevOps.