Everything we have seen so far has been conceptual: what a microservice is, what you gain and what you pay, how it compares with the monolith, and when to take the step. From here on, the course becomes practical, and for the practical part to make sense we need a realistic case that accompanies us from start to finish. That case is TechCorp and its online store, techcorp-shop.

In this lesson we present the running example in full detail: who TechCorp is and who the people making the decisions are, what its current monolith looks like, which concrete problems it suffers, which core business flow we will use over and over ("a customer places an order"), a real fragment of the current code that will serve as the starting point, the map of services we will build, the chosen technology stack, and a roadmap explaining what each module will advance on this case. We will not yet design the service boundaries (that is module 2's job) or implement anything (module 4): here we only set the scene and the rules of the game.

Contents

  1. Who TechCorp is
  2. The store today: a Node.js/Express monolith on a single PostgreSQL
  3. The six functional areas
  4. The concrete problems TechCorp suffers
  5. The core flow: "a customer places an order"
  6. A fragment of the current monolith: createOrder
  7. The target service map
  8. The chosen technology stack and why
  9. Roadmap of the case throughout the course
  10. Common mistakes and tips
  11. Exercises
  12. Conclusion

  1. Who TechCorp is

TechCorp is a fictional e-commerce company that sells consumer electronics (headphones, speakers, accessories, small devices) through its online store, techcorp-shop. All the data that will appear in the course (customers, products, amounts, orders) is made up.

Context data we will keep using:

Aspect Situation
Age of the store About seven years in production
Usual volume On the order of 3,000 orders per day on a normal day
Peaks Black Friday and January sales: catalog browsing multiplied by 20, orders by 3-4
Technical team About 25 people: development, QA and systems
Current organization A "back-end team", a "front-end team" and a "systems team"; the back-end is starting to organize informally by area

Two people will appear constantly:

  • Marta, TechCorp's CTO. She decides the technical strategy, defends (or not) investments before management, and has reached the conclusion, after applying the criteria from the previous lesson, that the store needs to evolve toward microservices incrementally. Marta will set the business constraints: the store cannot stop, the budget is not unlimited, every step has to deliver value.
  • Luis, lead of the Orders team. He is responsible for the most delicate area of the store (where customers, catalog, stock, payments and notifications intersect) and will be our technical protagonist: most of the code we write in the course will be that of orders-service, and we will see many decisions from his point of view.

  1. The store today: a Node.js/Express monolith on a single PostgreSQL

techcorp-shop is a single Node.js 20 with Express project, written in JavaScript, that runs as one process (replicated on three identical servers behind a load balancer) and uses a single PostgreSQL database holding all the tables of all the areas.

Simplified structure of the current repository:

techcorp-shop/
├── server.js                 # starts Express and registers all the routes
├── routes/
│   ├── customers.js
│   ├── catalog.js
│   ├── inventory.js
│   ├── orders.js
│   ├── payments.js
│   └── notifications.js
├── controllers/
│   ├── customersController.js
│   ├── catalogController.js
│   ├── ordersController.js       # createOrder lives here
│   └── ...
├── db/
│   ├── connection.js             # a single PostgreSQL pool
│   └── migrations/               # all the tables together
├── services/
│   ├── email.js                  # email delivery
│   └── paymentProvider.js        # call to the payment provider
└── package.json

And the database schema, heavily summarized:

-- All in the same "techcorp" database
CREATE TABLE customers       (id SERIAL PRIMARY KEY, email TEXT, name TEXT, address TEXT);
CREATE TABLE products        (id SERIAL PRIMARY KEY, name TEXT, price NUMERIC(10,2), category TEXT, active BOOLEAN);
CREATE TABLE stock           (product_id INT REFERENCES products(id), quantity INT, reserved INT);
CREATE TABLE orders          (id SERIAL PRIMARY KEY, customer_id INT REFERENCES customers(id), status TEXT, total NUMERIC(10,2), created_at TIMESTAMP);
CREATE TABLE order_lines     (order_id INT REFERENCES orders(id), product_id INT REFERENCES products(id), quantity INT, unit_price NUMERIC(10,2));
CREATE TABLE payments        (id SERIAL PRIMARY KEY, order_id INT REFERENCES orders(id), amount NUMERIC(10,2), status TEXT, provider_reference TEXT);
CREATE TABLE notifications   (id SERIAL PRIMARY KEY, customer_id INT, type TEXT, sent_at TIMESTAMP);

Notice the foreign keys crossing between areas (orders.customer_id → customers, order_lines.product_id → products, payments.order_id → orders). Today they are enormously convenient; in module 2 we will see that they are also the main obstacle to separating the data.

  1. The six functional areas

The monolith groups six business areas, which today are folders and tables inside the same project and tomorrow will be services:

Area What it does today Main tables
Customers Sign-up, login, profile, shipping addresses. customers
Catalog Product pages, categories, prices, search. products
Inventory Available quantities per product, reservations when ordering, warehouse receipts. stock
Orders Creation and lifecycle of the order (pending, confirmed, cancelled, shipped). orders, order_lines
Payments Charging through the external payment provider, recording payments and refunds. payments
Notifications Sending emails and SMS to the customer (confirmation, shipping, incidents). notifications

These six areas will map, one to one, onto the six services of the target map. Such a direct correspondence is a deliberate simplification for the course; in real life, finding the right boundaries is a job in itself, which we will tackle in module 2.

  1. The concrete problems TechCorp suffers

Marta does not want microservices out of fashion. She wants them because the store has measurable problems that match the signs from lesson 01-04:

  1. Weekly deployments made in fear. The whole store is deployed on Thursday nights. The test suite takes 40 minutes; the deployment, with manual checks, two hours. In the last quarter, four out of twelve deployments were fully or partially rolled back. Any urgent fix waits for the following Thursday or requires an emergency deployment of the whole application.

  2. Outages during campaigns. On the last Black Friday, catalog browsing traffic saturated the three servers. Because the catalog shares its process and database with everything else, order creation and charging went down too: the store did not sell for 50 minutes on the highest-sales day of the year. To avoid that, systems replicated the whole monolith to ten servers during the campaign, paying for payments and customers capacity that was not needed.

  3. A team stepping on itself. Developers from the different areas work on the same repository and the same tables. When the Notifications team changed a query on orders for a new email, it broke an Orders report. When Orders added a column to order_lines, the migration failed in production because of a lock held by a heavy Catalog query. Pull requests get stuck on conflicts, and Luis's team estimates it spends 20% of its time coordinating with other teams.

  4. Incidents that propagate. A month earlier, a failure of the email provider caused email delivery to start piling up open connections; the memory leak ended up taking down the entire process, charging included.

  5. A forced data model for the catalog. Products have highly variable attributes (some have a size, others a voltage, others compatibility) and in PostgreSQL this has ended up as a generic key-value product_attributes table that is awkward to query and to maintain.

These five problems are the "why" of the whole course. Each later module will solve one of them.

  1. The core flow: "a customer places an order"

Of all the flows in the store, one crosses all the areas: a customer places an order. It is the flow with the most business value, the one involving the most areas, and the one that concentrates the most problems. That is why it will be the recurring example throughout the course: we will model it, split it, implement it, deploy it, monitor it and secure it.

The steps, as they happen today in the monolith:

  1. The customer, already identified, submits their cart (customerId and a list of productId with quantities).
  2. The system checks that the customer exists and retrieves their address.
  3. It looks up the products to get the name and current price.
  4. It checks the stock of each product and reserves it (increments stock.reserved).
  5. It computes the total and creates the order in status PENDING with its lines.
  6. It charges the customer by calling the external payment provider and records the payment.
  7. If the charge succeeds, the order moves to CONFIRMED, the reserved stock is definitively deducted, and the confirmation email is sent.
  8. If the charge fails, the stock reservation is released, the order moves to CANCELLED, and an incident email is sent.

All of this happens within a single HTTP request and, almost all of it, within a single database transaction.

sequenceDiagram
    autonumber
    actor C as Customer
    participant M as techcorp-shop monolith
    participant DB as PostgreSQL (single)
    participant PP as Payment provider (external)
    participant SMTP as Mail server (external)

    C->>M: POST /orders {customerId, lines}
    M->>DB: BEGIN
    M->>DB: SELECT customer
    M->>DB: SELECT products (price)
    M->>DB: UPDATE stock SET reserved = reserved + quantity
    M->>DB: INSERT order (PENDING) + lines
    M->>PP: charge(total)
    alt charge succeeds
        PP-->>M: OK, reference
        M->>DB: INSERT payment; UPDATE order = CONFIRMED; UPDATE stock (deduct)
        M->>DB: COMMIT
        M->>SMTP: send confirmation email
        M-->>C: 201 Created {orderId, status: CONFIRMED}
    else charge rejected
        PP-->>M: rejected
        M->>DB: ROLLBACK (undoes reservation and order)
        M->>SMTP: send incident email
        M-->>C: 402 Payment Required
    end

Once the store is split into services, this same flow will become a choreography of events: orders-service will create the order and publish order.created; inventory-service will reserve stock and publish stock.reserved; payments-service will charge and publish payment.confirmed; orders-service will confirm the order and publish order.confirmed (or order.cancelled if something fails); and notifications-service will send the email. We will design that version in module 2 and build it in module 4; for now, keep the monolithic version and the event names in mind, because they will reappear constantly:

Event Who publishes it What it means
order.created orders-service An order has been recorded in status PENDING.
stock.reserved inventory-service The stock for the order lines has been reserved.
payment.confirmed payments-service The payment provider has accepted the charge.
order.confirmed orders-service The order is complete: stock and payment are fine.
order.cancelled orders-service The order could not be completed (out of stock, payment rejected...).

  1. A fragment of the current monolith: createOrder

This is, simplified but faithful to the spirit of the real code, the Express controller that implements the flow above today. Read it calmly: it is the starting point of the whole course, and we will come back to it to decompose it (module 2), extract services (module 4) and compare it with the final result (module 8).

// controllers/ordersController.js  (techcorp-shop monolith, current version)
const db = require('../db/connection');            // single PostgreSQL pool
const paymentProvider = require('../services/paymentProvider');
const email = require('../services/email');

async function createOrder(req, res) {
  const { customerId, lines } = req.body;          // lines: [{ productId, quantity }]
  const client = await db.connect();               // one connection for the whole operation

  try {
    await client.query('BEGIN');

    // 1. Customer data (table from ANOTHER area: customers)
    const { rows: [customerData] } = await client.query(
      'SELECT id, email, name FROM customers WHERE id = $1', [customerId]);
    if (!customerData) throw new Error('CUSTOMER_NOT_FOUND');

    // 2. Current prices (table from ANOTHER area: catalog)
    const ids = lines.map(l => l.productId);
    const { rows: products } = await client.query(
      'SELECT id, name, price FROM products WHERE id = ANY($1) AND active = true', [ids]);
    if (products.length !== ids.length) throw new Error('PRODUCT_UNAVAILABLE');

    // 3. Check and reserve stock (table from ANOTHER area: inventory)
    let total = 0;
    for (const line of lines) {
      const product = products.find(p => p.id === line.productId);
      const { rowCount } = await client.query(
        `UPDATE stock SET reserved = reserved + $1
          WHERE product_id = $2 AND quantity - reserved >= $1`,
        [line.quantity, line.productId]);
      if (rowCount === 0) throw new Error('OUT_OF_STOCK');
      total += product.price * line.quantity;
    }

    // 4. Create the order and its lines (tables owned by the orders area)
    const { rows: [order] } = await client.query(
      `INSERT INTO orders (customer_id, status, total, created_at)
       VALUES ($1, 'PENDING', $2, NOW()) RETURNING id`, [customerId, total]);
    for (const line of lines) {
      const product = products.find(p => p.id === line.productId);
      await client.query(
        `INSERT INTO order_lines (order_id, product_id, quantity, unit_price)
         VALUES ($1, $2, $3, $4)`, [order.id, line.productId, line.quantity, product.price]);
    }

    // 5. Charge (synchronous call to an external provider, in the middle of the transaction)
    const chargeResult = await paymentProvider.charge({ amount: total, customerId, orderId: order.id });
    if (!chargeResult.ok) throw new Error('PAYMENT_REJECTED');

    // 6. Record the payment and confirm (table from ANOTHER area: payments)
    await client.query(
      `INSERT INTO payments (order_id, amount, status, provider_reference)
       VALUES ($1, $2, 'CONFIRMED', $3)`, [order.id, total, chargeResult.reference]);
    await client.query(`UPDATE orders SET status = 'CONFIRMED' WHERE id = $1`, [order.id]);
    for (const line of lines) {
      await client.query(
        `UPDATE stock SET quantity = quantity - $1, reserved = reserved - $1 WHERE product_id = $2`,
        [line.quantity, line.productId]);
    }

    await client.query('COMMIT');

    // 7. Send the email (notifications area), outside the transaction but in the same request
    await email.send({
      to: customerData.email,
      subject: `Order ${order.id} confirmed`,
      body: `Hi ${customerData.name}, your order for €${total} is confirmed.`
    });

    return res.status(201).json({ orderId: order.id, status: 'CONFIRMED', total });

  } catch (error) {
    await client.query('ROLLBACK');
    const codes = { CUSTOMER_NOT_FOUND: 404, PRODUCT_UNAVAILABLE: 400, OUT_OF_STOCK: 409, PAYMENT_REJECTED: 402 };
    return res.status(codes[error.message] || 500).json({ error: error.message });
  } finally {
    client.release();
  }
}

module.exports = { createOrder };

What to notice in this code, because each point will be a topic in the course:

  • One function does six things from five different areas: it validates the customer, queries the catalog, reserves inventory, creates the order, charges and notifies. It is easy to read, but any change in any area goes through here.
  • Direct access to tables from other areas (customers, products, stock, payments). This is what makes it impossible for Notifications to change its schema without warning Orders, and vice versa. Lesson 02-04 will be precisely about breaking this.
  • One transaction protects everything: if the payment fails, the ROLLBACK undoes the stock reservation and the order. It is the convenience we will lose when we separate databases and that lesson 02-05 will replace with a saga.
  • An external call (the payment provider) inside the transaction: while the provider responds (sometimes seconds), the stock rows stay locked for every other order. During campaigns, this contributes to the saturation.
  • Email delivery is synchronous: if the mail server is slow or fails, the response to the customer is slow or fails, even though the order has been perfectly charged. This is what asynchronous, event-driven notifications will solve in module 3.
  • No idempotency: if the customer clicks "buy" twice, two orders are created and the customer is charged twice. Today the front end prevents this; in a distributed system, that will not be enough.

  1. The target service map

This is the system we will build step by step. The names, ports and databases are fixed for the whole course; we will reuse them in the code, in the Docker Compose files and in the Kubernetes manifests.

Service Port Responsibility Database
customers-service 3004 Sign-up, customer authentication (delegated to Keycloak), profile and addresses. PostgreSQL (customers)
catalog-service 3001 Product pages, categories, prices, search. Read-heavy. MongoDB (catalog)
inventory-service 3006 Available stock, reservations and releases, warehouse receipts. PostgreSQL (inventory)
orders-service 3002 Creation and lifecycle of the order; coordinates the flow through events. PostgreSQL (orders)
payments-service 3003 Charges against the external payment provider, recording of payments and refunds. PostgreSQL (payments)
notifications-service 3005 Sending emails and SMS based on events from other services. No significant database of its own (RabbitMQ queue and a minimal delivery log)
API Gateway 8080 Single entry point: routing, JWT authentication, rate limits.

And the supporting infrastructure that will surround the services:

Piece Role
RabbitMQ Message broker for the events order.created, stock.reserved, payment.confirmed, order.confirmed, order.cancelled.
Keycloak Identity server (OAuth2 / OpenID Connect) that issues the JWTs the gateway and the services validate.
Prometheus, Grafana, Loki Metrics, dashboards and centralized logs.
OpenTelemetry + Jaeger Distributed traces to follow an order across all the services.
Docker / Docker Compose Packaging and local development environment.
Kubernetes (+ Istio) Production orchestration and service mesh.
GitHub Actions Continuous integration and deployment pipelines.
flowchart TB
    Customer[Browser / Mobile app] --> GW[API Gateway :8080]
    KC[Keycloak] -. JWT .-> GW
    GW --> CUS[customers-service :3004]
    GW --> CAT[catalog-service :3001]
    GW --> ORD[orders-service :3002]
    CUS --> DB1[(PG customers)]
    CAT --> DB2[(MongoDB)]
    ORD --> DB3[(PG orders)]
    INV[inventory-service :3006] --> DB4[(PG inventory)]
    PAY[payments-service :3003] --> DB5[(PG payments)]
    NOT[notifications-service :3005]
    ORD <-. events .-> MQ[(RabbitMQ)]
    MQ <-. events .-> INV
    MQ <-. events .-> PAY
    MQ -. events .-> NOT
    PAY --> PP[External payment provider]
    NOT --> SMTP[External email / SMS]

  1. The chosen technology stack and why

Marta and the team leads have fixed the stack using two criteria: continuity with what the team already knows (so as not to learn a new language at the same time as a new architecture) and market standards for the remaining pieces.

Decision Choice Why
Language and framework for the services Node.js 20 + Express (JavaScript) It is what the monolith already uses; the team is fluent in it. Microservices would allow other languages, but TechCorp has no reason for that today. Identifiers in English (createOrder, OrderRepository, customerId) for consistency with the existing code.
Relational database PostgreSQL (one per service) Already known and operated; it fits orders, payments, inventory and customers, where local transactions matter.
Catalog database MongoDB It solves the real problem of variable product attributes. It is the only case of justified heterogeneity.
Messaging RabbitMQ A mature broker, simple to operate at TechCorp's scale, with support for acknowledgments and dead-letter queues.
Packaging and local environment Docker and Docker Compose The de facto standard; lets you bring up the whole store on a laptop.
Orchestration Kubernetes The de facto standard for running containers in production; the systems team has already tried it.
CI/CD GitHub Actions The code is already on GitHub; it avoids yet another tool.
Observability Prometheus, Grafana, Loki, OpenTelemetry, Jaeger A widely used open-source set covering metrics, dashboards, logs and traces.
Security JWT/OAuth2 with Keycloak Centralized, standard identity; the services only validate tokens.
Service mesh Istio Encryption between services, policies and network observability without touching the services' code. Introduced at the end, once everything else works.

An important note for your learning: these choices are reasonable, not the only ones. In lesson 04-01 we will discuss alternatives (Kafka versus RabbitMQ, other languages, other orchestrators). Here we simply lay the ground so that all the examples in the course are consistent.

  1. Roadmap of the case throughout the course

This is how TechCorp's story will progress module by module. Each row answers the question "what happens to the store in this module?".

Module What the TechCorp case advances TechCorp problem it attacks
1. Introduction (this one) The scene, the core flow and the target map are set. Marta decides to migrate incrementally. Understanding the why.
2. Design The six areas are analyzed, their boundaries (bounded contexts) defined, ownership of data decided, and the big createOrder transaction replaced by an event-based saga. Teams stepping on each other; single transaction.
3. Communication The REST APIs of each service are designed, along with the RabbitMQ events of the order flow, the gateway on 8080, how services find each other and how contracts are versioned. Coupling between areas; synchronous email.
4. Implementation The services are actually built in Node.js/Express, starting with orders-service alongside Luis: configuration, consuming APIs, publishing events and testing (unit, integration, contract). The real starting point of the code.
5. Deployment The services are packaged with Docker, the store is brought up with Docker Compose and then on Kubernetes, pipelines are set up in GitHub Actions, and catalog-service is deployed as a canary. Istio is added. Weekly deployments made in fear.
6. Monitoring Metrics, logs and traces of the order flow are instrumented; retries, circuit breakers and dead-letter queues are designed; the catalog is scaled for Black Friday; SLOs and alerts are defined. Outages during campaigns; incidents that propagate.
7. Security The gateway is protected with Keycloak JWTs, communication between services is encrypted, and containers and cluster are hardened. The attack surface of a distributed system.
8. Case studies The complete migration is walked through from start to finish (strangler pattern), the full implementation and deployment of the system are shown, and lessons are drawn. Consolidating everything.
flowchart LR
    M1[M1<br/>Scenario] --> M2[M2<br/>Boundary and<br/>data design] --> M3[M3<br/>APIs, events<br/>and gateway] --> M4[M4<br/>Service<br/>code]
    M4 --> M5[M5<br/>Docker, K8s,<br/>CI/CD] --> M6[M6<br/>Observability<br/>and resilience] --> M7[M7<br/>Security] --> M8[M8<br/>Full migration<br/>and lessons]

A detail worth keeping in mind from now on: the course does not do a "big bang". TechCorp will not switch the monolith off on a Friday to switch six services on the following Monday. The services will be extracted one by one, starting with the catalog (the clearest scaling reason and the lowest risk), then the order flow, and the monolith will keep slimming down until it disappears. That incremental process is detailed in lesson 08-01.

Common Mistakes and Tips

  • Losing sight of the why. When in module 5 you are wrestling with a Kubernetes manifest, remember the five problems from section 4: every piece of infrastructure is there to solve one of them, not for its own sake.
  • Idealizing the destination. The service map in section 7 is the goal, but it will be built step by step, and some decisions will be revisited along the way (that is normal in a real project).
  • Looking down on the monolith's code. createOrder is reasonable code for a monolith; it is not "bad", it is inadequate for the problem TechCorp has now. Understanding it well is the key to decomposing it well.
  • Changing the names. Keep the names of services, ports and events exactly as they appear in the tables of this lesson; the rest of the course takes them for granted.
  • Tip: keep a mental (or real) copy of the sequence diagram in section 5. You will compare it with its event-based version in module 2 and with the real distributed trace in module 6, and that comparison is one of the best ways to understand what changes with microservices.

Exercises

Exercise 1: Tracing the flow

Without looking at the sequence diagram, write in order the eight steps of the "a customer places an order" flow as it happens today in the monolith, and indicate for each step which functional area it belongs to.

Exercise 2: Reading createOrder with an architect's eyes

About the fragment in section 6, answer:

  1. Which tables does it query or modify that do not belong to the orders area?
  2. What happens if the payment provider takes 15 seconds to respond? Who is affected?
  3. What happens if sending the email fails after the COMMIT? What does the customer see and what is left in the database?

Exercise 3: Matching problems and modules

For each of the five problems in section 4, indicate which module (or modules) of the course will address it and which piece of the target map or the stack it relates to.

Solutions

Exercise 1

  1. The customer submits the cart → Orders (entry point).
  2. Check the customer and retrieve the address → Customers.
  3. Look up products and prices → Catalog.
  4. Check and reserve stock → Inventory.
  5. Compute the total and create the PENDING order → Orders.
  6. Charge through the payment provider and record the payment → Payments.
  7. Confirm the order, deduct stock and send the email → Orders, Inventory and Notifications.
  8. If the charge fails: release the reservation, cancel and notify the incident → Inventory, Orders and Notifications.

Exercise 2

  1. customers (customers area), products (catalog), stock (inventory) and payments (payments). Only orders and order_lines are its own.
  2. The transaction stays open during those 15 seconds, with the stock rows for those products locked by the UPDATE. Any other order that includes any of those products waits. During a campaign, many orders waiting on locks exhaust the connections and the whole system degrades. On top of that, the customer sees the page "loading" for 15 seconds.
  3. The order is confirmed, charged and with stock deducted in the database (the COMMIT has already run). But email.send throws, the catch runs a ROLLBACK (which no longer undoes anything, because the transaction is over) and responds to the customer with a 500. The customer believes their purchase failed, even though they have been charged; they will probably try again and be charged twice. It is a perfect example of why notifications must be asynchronous and decoupled.

Exercise 3

Problem Modules Related pieces
Weekly deployments made in fear 5 (Docker, Kubernetes, CI/CD, deployment strategies) and 4 (per-service tests) GitHub Actions, containers, canary deployment
Outages during campaigns 6 (scalability, resilience) and 2/3 (catalog as a separate service) catalog-service scaled independently, Prometheus/Grafana
A team stepping on itself 2 (boundaries and one database per service) and 3 (contracts) Bounded contexts, versioned APIs
Incidents that propagate 3 (asynchronous messaging) and 6 (error handling, circuit breakers) RabbitMQ, isolated notifications-service
Forced data model for the catalog 2 (one database per service) and 4 (implementation) MongoDB in catalog-service

Conclusion

In this lesson we presented in depth the case that runs through the course: TechCorp, an online store that today is a Node.js/Express monolith on a single PostgreSQL with six functional areas, and that suffers concrete, measurable problems: dreaded weekly deployments, outages during campaigns because of catalog saturation, teams stepping on each other over the same code and the same tables, incidents that propagate from secondary areas to critical ones, and a forced data model in the catalog. We walked step by step through the core flow "a customer places an order" and read the real code of createOrder, which concentrates the work of five areas in a single function and a single transaction: that fragment is our starting point. We fixed the target map (six services with their ports and databases plus a gateway), the technology stack and its reasons, the five events of the order flow, and a module-by-module roadmap.

With the scene set, module 2 begins the real work: designing the microservices. We will start from the design principles, learn to decompose TechCorp's monolith, define its bounded contexts, decide how to distribute the data among services, and replace the big createOrder transaction with a saga coordinated through events. Marta has made the decision; from now on we accompany Luis and his team in the execution.

Microservices Course

Module 1: Introduction to Microservices

Module 2: Microservice Design

Module 3: Communication between Microservices

Module 4: Implementing Microservices

Module 5: Deployment and Orchestration

Module 6: Monitoring and Maintenance

Module 7: Security in Microservices

Module 8: Case Studies and Practical Examples

© Copyright 2026. All rights reserved