What is Microservices?

Microservices are an approach to building an application as a collection of services that can be developed, deployed and operated independently. Each service has a clear responsibility, exposes defined interfaces and controls its own domain data. The benefit is the ability to change or scale one capability without releasing the whole application; the cost is managing communication, consistency and failure across a distributed system.
The important distinction is independence, not simply small code or many containers. Several processes that must always be changed and released together can become a distributed monolith: the coordination of a monolith combined with the network problems of separate services.
What makes a service a microservice?
A service boundary should enclose a coherent capability, such as maintaining a catalogue, accepting orders or managing stock. There is no universal line count, container count or maximum team size that makes a service micro. The architecture is judged by its responsibilities and ability to evolve.
James Lewis and Martin Fowler’s 2014 description of microservices established independently deployable services organised around business capabilities as central characteristics. It is an influential architectural account, not a formal networking standard or a mandatory implementation specification.
A defined contract explains what callers can request or what events consumers receive.
The service owns its behaviour and authoritative data rather than depending on direct access to another service’s tables.
Its deployment lifecycle can progress without requiring every neighbouring service to be redeployed.
An accountable team can test, monitor and support it throughout its life.
Operational dependencies still exist. Independent deployment does not mean that the service works without any other system.
The infographic shows an illustrative shopping application. Catalogue, Orders and Stock are separate capabilities. Updating Orders to version 2 leaves the other services on version 1, provided their contracts remain compatible.

Microservices vs a monolith
Design | Deployment and communication | Practical trade off |
|---|---|---|
Monolith | Application modules are released as one unit. Many interactions remain inside the process. | Simpler local calls and transactions; the release can affect the whole application. |
Modular monolith | One deployable application with deliberately enforced internal boundaries. | Maintains cohesion without adding remote calls between every module. |
Microservices | Capabilities have separate release lifecycles and communicate across process boundaries. | Selective deployment and scaling, with distributed operational responsibilities. |
Distributed monolith | Components run separately but changes require coordinated releases. | Network complexity with limited practical deployment independence. |
A monolith can be well structured, tested and replicated across several servers. It does not mean one machine, poor code or an inability to scale. Equally, drawing separate boxes around tightly coupled code does not remove that coupling.
Fowler’s microservice trade offs explains why autonomy can be valuable while distribution and operations impose costs. The question is which constraints you need to solve, rather than which label sounds more modern.
Choose boundaries around behaviour and change
Start with the work the application performs and the rules it must preserve. A bounded context is a boundary within which a domain model and its terminology have a defined meaning. An account in billing can mean something different from an account in identity management.
A useful boundary contains behaviour that changes together. Splitting validation, business logic and database access into three compulsory network calls can separate technical layers while leaving one capability dependent on all three releases.
Microsoft’s service boundary guidance recommends evaluating cohesion, release dependencies, communication volume and consistency needs. A bounded context informs the design; it does not mechanically dictate one service per database table.
Which rules need to be enforced in one atomic operation?
Which changes repeatedly require coordinated edits across services?
Does one service spend most of its time asking another for tiny pieces of data?
Do different capabilities have materially different scaling or release needs?
Can a team own the capability without constant cross team handovers?
Frequent coordinated changes or chatty calls are signals to review the boundary. A larger cohesive service can be more useful than several tiny services that must always move together.
How a request travels through microservices
Consider an illustrative order submission. The customer sees one application, although several internal services participate. An API defines the interface between those components.
The client sends an authenticated order request to the application’s public entry point.
A gateway routes it to Orders, with the policies configured for that request.
Orders checks the required information and asks Stock to reserve items using a defined operation.
The participating services persist their own state and the workflow records progress.
An order event can be delivered through a broker to Notifications, which sends the appropriate message.
The client receives a result or a pending status that reflects what has actually completed.
This sequence is a conceptual example, not a universal checkout design. Payments, reservation expiry and cancellation introduce additional states. A gateway is common but not mandatory, and not every internal service needs a public endpoint.
The lower path in the infographic shows Orders publishing an event to a broker, then Notifications consuming it. The browser does not directly publish that internal event. A successful response should distinguish an accepted request from a completed business operation.
API calls and asynchronous messages
Mechanism | What the caller depends on | Typical consideration |
|---|---|---|
Request and response | A usable response within its deadline. | Direct answers, but latency and availability dependencies can accumulate. |
Command through a queue | Durable acceptance and later processing according to the system’s contract. | Track completion, errors and duplicate delivery. |
Published event | Consumers interpret a fact that has happened, such as OrderAccepted. | Define schemas, ordering scope and how consumers recover. |
An HTTP client using asynchronous programming still has a request and response dependency if the application needs the answer before continuing. Nonblocking I/O and an asynchronous business workflow solve different problems.
Microsoft’s interservice communication guide sets out these distinctions. Queues can buffer bursts and let consumers recover independently, but broker outages, retained backlog and slow consumers remain operational concerns.
Define deadlines, error meanings, event schemas and version behaviour explicitly. REST over HTTP and gRPC are possible interfaces; neither makes poor boundaries disappear. An event architecture is also possible inside a monolith and is not synonymous with microservices.
Data ownership does not mean one database server per service
Each service should control the data and schema belonging to its capability. Other services use its contract or maintain permitted copies from published information. Directly editing another service’s tables makes its private implementation a dependency.
Microsoft’s data considerations makes a useful distinction: services can share a physical database server while keeping their schemas and access ownership separate. Sharing the same tables is the coupling problem; physical separation is also a capacity, reliability and security decision.
For example, Stock can own reservation records while Orders stores the reservation identifier and relevant order facts. A reporting view might contain copies from both services. That view needs a freshness contract and should not quietly become the authoritative place to alter stock.
A service can use a relational transaction within its own store. Once an operation crosses several independently managed stores, local commits do not automatically become one globally atomic transaction.
Consistency, sagas and reliable event publication
Eventual consistency means copies can temporarily disagree while updates propagate. It is a deliberate consistency model, not permission to lose updates indefinitely. Identify what users see while work is pending, how conflicts are resolved and what happens when progress stops.
For a hypothetical order, stock may be reserved before payment is confirmed. A failed payment can trigger release of the reservation. Those are separate committed operations. Releasing stock is compensation, rather than rewinding time as if nothing happened.
The Saga pattern coordinates local transactions and compensating actions. Choreography lets services react to events; orchestration records and directs the workflow centrally. A saga does not provide automatic global isolation, and compensation can itself fail.
There is another failure window when a service commits a database update and then crashes before publishing its event. A transactional outbox records the state update and event intent in the same local transaction; a relay subsequently sends the event.
AWS’s transactional outbox guidance describes that mechanism. Delivery may occur more than once, so consumers need appropriate duplicate handling. An outbox does not turn the entire workflow into an exactly once transaction.
Techie Broadband calculation: follow the critical path
Microservices can add network waits, but counting services alone cannot predict response time. What matters is the critical path: the sequence of dependent work that must complete before the response is ready.
Consider an illustrative backend operation with a 40 millisecond client to gateway round trip. It needs three service operations, each with a 4 millisecond internal round trip and 12 milliseconds of processing. Assume reused connections, negligible payload transmission, no queuing, no retries and no extra gateway processing.
Arrangement | Calculation | Illustrative response time |
|---|---|---|
Three dependent operations in sequence | 40 + 3 × (4 + 12) | 88 ms |
Three independent operations started together | 40 + max(16, 16, 16) | 56 ms |
Parallel operations, one with 120 ms processing | 40 + max(16, 16, 124) | 164 ms |
Techie Broadband calculation: parallelising independent work removes 32 milliseconds in this simplified case, about 36.4% of the 88 millisecond total. You cannot apply that change when the next operation needs the previous result. Parallel work also increases concurrent demand and waits for the slowest required branch.
These are theoretical examples, not measurements of a cloud, ISP or framework. Real traces include connection establishment, serialisation, database time, scheduling, network loss and contention. Percentiles such as p95 and p99 describe response time distributions; adding each component’s p99 does not generally produce the end to end p99.
For scale, a decimal 20 KB payload contains 160,000 bits. Its payload only transmission time at 100 Mbps is 1.6 milliseconds. That does not replace the 40 millisecond round trip or backend work. Higher bandwidth and lower latency address different constraints.
Failure isolation must be designed
A separate process can contain a crash, but synchronous callers can still depend on it. If a recommendations feature is optional, the page might omit it during an outage. If payment authorisation is required, pretending success would be incorrect.
Set connection and operation timeouts, with an overall deadline that includes downstream work.
Limit retries to failures that the contract allows you to retry safely.
Use backoff and jitter to spread recovery demand.
Bound concurrency and queues so a slow dependency cannot consume every worker.
Provide explicit degraded behaviour for optional features.
Persist workflow progress and define recovery for incomplete operations.
A circuit breaker temporarily stops calls after a configured failure threshold and later permits recovery checks. It differs from retrying and needs tested state transitions. A bulkhead separates resources, such as connection pools, so one failing dependency has a limited scope.
Retries can multiply load
Techie Broadband calculation: imagine four retrying call layers, each allowing one original attempt plus two retries. Under persistent failure, with no cancellation or deadline stopping the attempts, one top level operation can trigger up to 3 × 3 × 3 × 3 = 81 leaf attempts.
That is a theoretical maximum for the stated nesting, not normal request volume. Coordinated retry ownership, bounded attempts and shared deadlines can prevent the multiplication. AWS’s timeouts, retries and jitter explanation describes how recovery traffic can worsen overload.
A timeout does not prove the server did nothing. It may have committed the order before the response was lost. An idempotency mechanism associates repeated attempts with the same intended operation, according to a defined scope and retention period.
AWS’s idempotent API discussion explains why caller intent matters. Reusing one operation identifier for different order contents should not silently create a different order. Deduplication records and the state change also need a reliable relationship.
Scaling services and their dependencies
Selective scaling means adding capacity where a capability needs it. Three Orders application instances can serve the same logical Orders capability and use its owned data store. They are not three different microservices, nor do they automatically need three unrelated databases.
Additional instances help only if work can be shared safely and another component is not already limiting throughput. A saturated database, hot lock, broker partition or external API quota can remain the bottleneck. More replicas can even increase pressure on it.
Stateless request handlers simplify replication, but the application still has state. Sessions, idempotency records, reservation data and workflow progress must remain accessible in the chosen design. Scaling based solely on CPU can miss queue growth or exhausted connection pools.
Containers, Kubernetes, discovery and service meshes
Technology | Role | What it does not establish |
|---|---|---|
Container | Packages an application process and its dependencies. | A useful service boundary or independent business lifecycle. |
Kubernetes | Schedules workloads and manages their desired running state. | Correct transactions or compatible API changes. |
Service discovery | Finds eligible network endpoints for a service identity. | Permission, capacity or guaranteed request success. |
API gateway or reverse proxy | Routes requests and applies configured entry policies. | An application architecture by itself. |
Service mesh | Manages aspects of communication, policy and telemetry. | Domain ownership or business consistency. |
A microservice can run in a container, a virtual machine or an appropriate managed runtime. Kubernetes is an option rather than a requirement.
Service discovery keeps names connected to changing endpoints. A reverse proxy can use those endpoints to route traffic. Platform orchestration manages workloads; saga orchestration manages a business workflow. The shared word does not make those jobs interchangeable.
Istio’s service mesh glossary describes a layer for managed, observable and secure communication. Such a layer can centralise useful controls but adds its own configuration and resource costs. It is not compulsory for a small application.
Secure each trust boundary
Private networking does not remove the need to authenticate callers and authorise operations. A gateway may validate a public credential, but downstream handling still needs a trustworthy identity and the correct permissions for the requested object.
Restrict network access to intended callers and ports.
Apply least privilege to service identities and database accounts.
Protect traffic where required with correctly validated TLS; mTLS can authenticate both ends.
Rotate secrets and certificates without coordinating a complete application outage.
Validate inputs, limit resource consumption and control outbound destinations.
Keep sensitive data out of logs, event payloads and trace attributes unless needed and properly protected.
The OWASP API Security Top 10, 2023 edition highlights object authorisation, authentication and resource consumption risks. Dividing an application into services does not inherently fix those risks. More exposed interfaces can create more places to enforce and test policy.
Observability: trace one user operation
A service can report healthy while users experience a failing workflow. Collect useful metrics, logs and traces, and relate them to the same operation. Track request errors, latency distributions, saturation, queue age, downstream outcomes and release versions.
OpenTelemetry context propagation explains how context travels between processes. For HTTP, W3C Trace Context headers can connect spans into a causal trace. Messaging also needs context propagation if its work is to be associated with the originating operation.
Tracing is not proof that every request was captured. Sampling, missing instrumentation and broken propagation create gaps. Avoid counting a parent span’s elapsed time and all nested spans as separate sequential delays: child work can be contained or overlap.
Testing and independent releases
Independence depends on contracts remaining usable while versions overlap. Test service behaviour locally, its real dependencies in integration environments, consumer expectations through contract checks, and selected end to end workflows across the application.
A compatible change might add optional information while preserving existing meanings. Removing a field, changing units or making a previously optional value mandatory can break consumers. Database migrations need a staged approach if old and new application versions run together.
Microsoft’s API design guidance explains contract evolution, and its microservices delivery guidance covers release pipelines. The organisation can use one repository or several; repository count alone does not determine deployment independence.
Continuous Deployment can support frequent releases when suitable checks and recovery exist. Test failed dependencies, duplicate messages, delayed events and partial releases as well as the successful path. Reverting code does not automatically revert committed data or emitted events.
When microservices are worth the effort
Observed need | Potential value | Check first |
|---|---|---|
Different capabilities need different capacity | Scale the busy capability independently. | Will its database or downstream quota remain limiting? |
Several teams are blocked by one release | Release cohesive capabilities separately. | Are contracts and ownership stable enough? |
Distinct reliability or security requirements | Separate operating policies and resources. | Are shared hosts and dependencies still a common failure point? |
Small application with one team | A modular monolith can keep operations simpler. | Is distribution solving an actual present constraint? |
Unknown or rapidly changing domain | Coarse boundaries are easier to revise. | Would early splitting make refactoring slower? |
Fowler’s Monolith First discussion, published in June 2015, argues for learning the domain before paying the cost of distribution. It is contextual advice rather than a universal law. An experienced team with understood boundaries may have good reasons to start with services.
Count the whole cost: deployment pipelines, environments, on call support, broker operation, telemetry retention, certificates, backups, schema compatibility and incident diagnosis. Technology diversity is a possibility, not an obligation to maintain a different language for every service.
Migrate gradually and measure the result
Identify one capability with a credible reason to separate, establish its contract and data ownership, then route that work to the new implementation. Microsoft’s Strangler Fig pattern describes incremental replacement while the remaining legacy application continues operating.
Plan data movement and reconciliation explicitly. Running two implementations does not make their writes consistent. Keep a clear source of truth during each migration phase and decide how to return traffic if the new path fails.
Measure the reason for the change: release lead time, change failure impact, capacity constraints or user facing latency. A higher service count is not a success metric. Leaving a stable monolith alongside useful extracted services can be a sensible destination.
What microservices mean for UK broadband and home labs
A UK user normally reaches a public application through WiFi or Ethernet, a router, the access network, ISP routing and the remote entry point. Internal calls between colocated backend services usually stay in the hosting network; every microservice does not create another round trip over your home broadband.
If you deliberately split an application between a home lab and a cloud host, the connecting API calls do traverse that wider path. FTTP or FTTC capacity, latency, upload saturation, routing, a VPN and outages can then affect service interactions.
Remote callers receiving data from home depend on home upload speed. A name or container does not establish inbound access through CGNAT; a suitable reachable address or designed tunnel is a separate networking requirement.
Faster download speed can help large responses but cannot remove backend queue time or a long chain of dependent calls. Compare idle and loaded latency, isolate WiFi and inspect the actual application trace before blaming an ISP or changing package.
How to troubleshoot a microservices application
Define the failing user operation, expected result, timestamp and correlation identifier.
Separate inability to reach the public entry point from an application error after connection.
Check routing, discovery and permissions from the failing service’s network context, not only your laptop.
Trace the operation and identify the critical path, missing response or oldest queued work.
Compare versions and contracts, particularly after a partial deployment or schema change.
Inspect dependency latency, pool saturation, database contention and retry volume.
For events, check committed publication intent, broker acceptance, delivery, consumer progress and duplicate handling.
For inconsistent state, inspect workflow checkpoints and compensation outcomes before repeating the original action.
Check local networking and loaded broadband latency only where that path participates.
Change one suspected cause, repeat the controlled test and verify the user operation has recovered.
A running process, a successful DNS lookup and a healthy gateway test different layers. A message accepted by a broker does not prove a consumer completed it. If an operation might already have committed, use its status or idempotency contract before sending another potentially destructive request.
Frequently asked questions
Are microservices just small APIs?
No. An API is an interface. A microservice is a service with a coherent responsibility and an independently manageable lifecycle. Exposing many endpoints does not by itself create that architecture.
Do microservices need Docker or Kubernetes?
No. Containers and Kubernetes can help package and operate services, but they are deployment choices. Microservices can use other suitable runtimes and hosting arrangements.
Does every microservice need a separate physical database?
No. The key principle is ownership and access isolation for its domain data. Services can share a physical database server while keeping schemas and permissions separate, although shared infrastructure remains a common dependency.
Are microservices faster than a monolith?
Not inherently. Independent scaling can relieve a specific bottleneck, but remote calls, serialisation, queues and extra dependencies can add delay. Measure the complete operation and its critical path.
Can I learn microservices in a home lab?
Yes. A small example can demonstrate independent releases, contracts, retries and event handling. Running everything on one machine still leaves shared hardware and power failures; it does not demonstrate production availability.
Are microservices the same as SOA?
Microservices belong to the wider family of service oriented approaches. The term emphasises independent deployment and cohesive capabilities, but SOA has several interpretations. Compare the actual boundaries, data ownership and operating model rather than relying on labels.
Key takeaway
Microservices let an application evolve as independently managed capabilities connected through contracts. Useful boundaries can support separate releases and selective scaling, but network calls, distributed data and partial failures become part of normal engineering. Choose the architecture because those benefits solve a concrete constraint, then verify the complete user operation rather than the health of each box in isolation.
To explore the related technical concepts used in this Microservices guide, visit our broadband terminology guide.

