Microservices Designing a Service

Building a microservice starts with design decisions, not code. A poorly designed service causes pain for years. A well-designed one runs reliably, scales cleanly, and stays easy to change. This topic walks through how to design a microservice from first principles.

Step 1: Define the Service Boundary

The hardest part of microservices is deciding what belongs in one service and what belongs in another. The technique most teams use is called Domain-Driven Design (DDD).

DDD groups your system into bounded contexts — areas of the business that have their own language, rules, and data. Each bounded context becomes a candidate for a microservice.

Hospital System Example

Business Areas (Bounded Contexts):
+--------------------+   +--------------------+   +--------------------+
|    Patient Mgmt    |   |   Appointments     |   |    Billing         |
|                    |   |                    |   |                    |
| - Register patient |   | - Book slot        |   | - Create invoice   |
| - Update records   |   | - Cancel booking   |   | - Process payment  |
| - Medical history  |   | - Send reminders   |   | - Insurance claims |
+--------------------+   +--------------------+   +--------------------+

Each box = one microservice

Notice that "patient" means different things in each context. In Patient Management, a patient is a medical record. In Billing, a patient is a customer account. Each service defines "patient" for itself without sharing the definition.

Step 2: Define the API Contract

Before writing code, write down what the service accepts and what it returns. This is the API contract. Other teams design their services around this contract.

Appointment Service API Contract:

Endpoint: POST /appointments
Input:
  - patient_id (string)
  - doctor_id (string)
  - date (YYYY-MM-DD)
  - time (HH:MM)

Output:
  - appointment_id (string)
  - status: "confirmed" or "unavailable"
  - confirmation_code (string)

Document this contract before writing the service. Teams that consume your service can start building against this contract immediately — they do not need to wait for you to finish coding.

Step 3: Choose the Right Data Store

Each service owns its own data store. Choosing the right type of database for the service's workload matters.

Service Type             Best Database Type     Example
====================================================================
User profiles            Relational (SQL)       PostgreSQL, MySQL
Product catalog          Document (NoSQL)       MongoDB
Session tokens           Key-Value (Cache)      Redis
Search queries           Search Engine          Elasticsearch
Financial transactions   Relational (SQL)       PostgreSQL
Activity feeds           Time-series DB         InfluxDB

An Appointment Service deals with structured, relational data — a doctor, a patient, a time slot. PostgreSQL fits well. A notification service that logs millions of events per second fits better with a time-series database.

Step 4: Design for the Happy Path and Failure Path

Every service design includes two paths: what happens when everything works (happy path), and what happens when something fails (failure path).

APPOINTMENT BOOKING FLOW

Happy Path:
User --> Appointment Service --> Check Doctor Availability --> Book Slot --> Return Confirmation

Failure Path:
User --> Appointment Service --> Check Doctor Availability --> [Service Down]
                                                                    |
                                                           Return error message
                                                           Do NOT book anything
                                                           Log the failure

Design failure behavior explicitly. Never assume everything will work. What should the service return if it cannot reach the Payments Service? Should it retry? Should it fail fast? Answer these questions during design, not during a production outage.

Step 5: Define Events the Service Publishes

A well-designed service announces important things that happen inside it. These announcements are called events. Other services listen for events they care about.

Appointment Service publishes:
  - AppointmentBooked   { appointment_id, patient_id, doctor_id, date }
  - AppointmentCancelled { appointment_id, reason }

Who listens:
  - Notification Service listens to AppointmentBooked --> sends SMS reminder
  - Billing Service listens to AppointmentBooked --> creates draft invoice
  - Analytics Service listens to all events --> tracks doctor utilization

Publishing events keeps the Appointment Service from knowing about Notification or Billing logic. It just announces what happened. Others decide what to do with that information.

Step 6: Plan for Versioning

APIs change over time. A well-designed service includes the version in its URL from day one.

/v1/appointments   <-- Original API
/v2/appointments   <-- Updated API with new fields

Both versions run at the same time during a transition period. Old consumers stay on v1. New consumers use v2. This prevents breaking other services when you add new features.

A Design Checklist

  • Does the service have a single, clear responsibility?
  • Is the API contract documented before coding starts?
  • Does the service own its own database?
  • Have you defined behavior for network failures and slow dependencies?
  • Does the service publish events for key actions?
  • Does the API URL include a version number?
  • Can the service run and be tested without starting other services?

A "yes" on every item means the service is ready to build. A "no" means you have more design work to do before the first line of code.

Leave a Comment

Your email address will not be published. Required fields are marked *