← Back to TypeScript Course | Chapter 28: Real World Projects | Lesson 12 of 14

Microservices with TypeScript

Microservices divide an application into independently deployable services. TypeScript can provide clear contracts for requests, responses, configuration, and shared domain models.

Core Concept

In a TypeScript microservices architecture, each service can have its own independent tsconfig.json and dependencies, but shared request/response contracts between services still benefit from a common typed schema so they don't drift apart silently.

Example: Core Concept

typescript
interface OrderCreatedEvent {
  orderId: string;
  total: number;
}
// Each service has its own tsconfig, but shares this event's shape.
const event: OrderCreatedEvent = { orderId: "1", total: 50 };
console.log(event);

Basic Setup

A basic setup often uses a shared-types package (or generated types from a schema like Protobuf/OpenAPI) published to a private registry, imported by every service that needs to call or be called by another.

Example: Basic Setup

typescript
// shared-types package published to a private registry,
// imported by every service that produces/consumes these events.
interface OrderCreatedEvent { orderId: string; }
console.log("A shared-types package prevents contract drift between services");

Typed Example

A typed example: a shared interface OrderCreatedEvent { orderId: string; userId: string; total: number } is used both by the service that publishes the event and every service that subscribes to and processes it.

Example: Typed Example

typescript
interface OrderCreatedEvent {
  orderId: string;
  userId: string;
  total: number;
}
function publishOrderCreated(event: OrderCreatedEvent) {
  console.log("Publishing:", event);
}
publishOrderCreated({ orderId: "1", userId: "u1", total: 99 });

Project Usage

In a real project, versioning these shared inter-service types carefully matters more than in a monolith, since two services might deploy on different schedules and temporarily run against slightly different versions of a shared contract.

Example: Project Usage

typescript
interface OrderCreatedEventV2 {
  orderId: string;
  total: number;
  currency: string; // added in v2
}
console.log("Services on different deploy schedules may see different versions");

Best Practices

Validate incoming inter-service messages at runtime (not just compile time) at each service boundary, since TypeScript's types vanish at runtime and can't protect a service from a malformed message sent by another service running an older version.

Example: Best Practices

typescript
interface OrderCreatedEvent { orderId: string; total: number; }
function isOrderCreatedEvent(value: any): value is OrderCreatedEvent {
  return typeof value?.orderId === "string" && typeof value?.total === "number";
}
console.log(isOrderCreatedEvent({ orderId: "1", total: 10 }));

Login to run this code

C/C++/Java/PHP execution requires a free account. Your code is saved — you'll land right back in the editor after logging in.