A premium course by Khalil Stemmler

Domain-Driven Design w/ TypeScript & Node.js

Learn how to use Domain-Driven Design to build complex enterprise-level applications with Node.js & TypeScript.

Get notified

Ever wonder how huge complex apps are built?

Think business-logic heavy apps and organizations like Google, Microsoft and GitHub.

How do they do it?

Have you ever found yourself wondering:

  • Why is it that the more code I add to this project, the harder it becomes to maintain?
  • Where do I put business logic anyways?
  • Where do I put validation logic?
  • Does this design make sense?
  • How can I make this code cleaner?
  • How are real-life companies doing this?
  • How are senior developers writing code?
  • How do I write tests for this code?
  • and the list goes on...

What you'll build

We’ll build a Vinyl Trading Application complete with Billing, Notifications, Users & Identity Management supporting subdomains using DDD best practices.

We’ll use Node.js, Express.js, Sequelize ORM, Stripe and JWT for authentication.

What you'll learn

How to build complex applications with Node.js and TypeScript that actually get better instead of degrading over time

How to organize your application into subdomains and separate bounded contexts

How to design rich object-oriented software implementations of the problem domain

How to discover & organize business logic using Domain Events and Event Storming

How to encapsulate business rules and validation logic in Entities and Value Objects using factories

How to use Separation of Concerns to organize your app into testable layers

Want access to this course?

Get notified

Course outline

Introduction to Domain-Driven Design

Getting started

Why Domain-Driven Design?

Why TypeScript?

What projects are right for Domain-Driven Design?

The main concepts of Domain-Driven Design

Layered Architecture and an isolated Domain model

TDD and Unit Testing

Model-Driven Design

What are we building?


Understanding the problem, subdomains and bounded contexts

Goals of modeling a problem domain to a solution space

Separating the solution space in subdomains

Identifying the primary domain

Supporting & generic subdomains

Bounded contexts & subdomains

Involving Domain Experts to build a Ubiquitous Language


Getting started with Domain Modeling

The goals of modeling our domain

Domain modeling building blocks

Rich vs. Anemic Domain Models

TypeScript, Express.js and Sequelize project setup


The lifecycle of an Entity

Base Entity class

Generating Entity identity strategies

Creating entities using Factory Methods

TDD approach to identifying modeling our requirements

When to write Unit Tests

Don't follow the Red-green-refactor loop to a tee

Value Objects

Difference between Entities and Value Objects

Base Value Object class

Encapsulating validation logic in Value Objects


Persistence & UI Layers

Goals of the persistence layer separation of concerns

Recap of the Onion architecture

Designing a database schema for our application

Introducing the Sequelize ORM

Hooking up ORM models and migration scripts

Entity identity generation with UUIDs instead of auto-incremented primary keys

Introducing Repositories

To use generic repositories or not

Using Repositories to perform CRUD on domain models

Using Mappers to map ORM models to Domain Models

Using Mappers to map Domain Models to ORM models

DTOs for our API layer

Using Mappers to map Domain Models to DTOs

Other patterns: Unit of Work, transactions, repo.save()


Aggregates & Domain Events

Understanding the role of Aggregates

Identifying an Aggregate

Base Aggregate class

Understanding how Domain Events allow us to co-locate domain logic

Domain Events using the Publish/subscribe pattern

Event storming to identify our domain events

Creating our first Domain Events

When to use domain services

Subscribing to Domain Events (same subdomain, same bounded context)

Subscribing to Domain Events (separate subdomain, same bounded context)

Subscribing to Domain Events (separate subdomain, separate bounded context)

Messaging Queues

Anti-corruption layers


Additional bounded contexts and onwards

Goals of the separate bounded context

Context maps and boundaries

Communication between separate bounded contexts

Application Services

To use the Use Case pattern or not

The role of the UI

Splitting bounded contexts in microservices

Packaging by module

Domain modeling improvements

DDD anti-patterns


Throughout the Domain-Driven Design w/ TypeScript course, you'll learn everything you need to design and develop complex business-logic heavy applications with Node.js & TypeScript.

Get notified when this course and other advanced Node.js & TypeScript courses come out

Get notified

Meet the instructor

Khalil Stemmler

Software Essentialist ⚡

Khalil is a software developer, writer, musician, and ex-failed-startup co-founder of Univjobs. He has 6+ years of experience writing software with Java, JavaScript, Node.js, and as of late: TypeScript. He writes about software design and architecture best practices with TypeScript and is especially passionate about Domain-Driven Design and GraphQL.