I'm Bob!

Find me on Twitter
Find slides on Github
Read my blog
Read my book

Talk to me about

  • Climate change
  • How to find work in climate
  • How to do your first talk
  • DDD and serverless architectures

Why does this matter?

Boundaries are hard to get right

Boundaries are hard to change

Three lenses





"Egg balanced on Spoons - TROML - 647" by Clint__Budd is licensed under CC BY 2.0 .

Is coupling bad?

Coupling is necessary

Re-use is coupling

API Types are repeated!

DRY is not an improvement

Is reuse bad?

Of course not!

but we have to be mindful of coupling

Temporal coupling

Temporal coupling in book borrowing

Event-Driven architecture reduces temporal coupling

Small is beautiful

This is how Cazoo works


"letter jumble" by Sky Noir is licensed under CC BY-NC 2.0 .

What is consistency?

Requests through a system should see a coherent state

Consistency matters when making decisions

Strong consistency

All requests see all updates in the same order

Eventual consistency

States converge to a single view over time

Consistency is the first casualty of temporal decoupling

An eventually consistent story

"A lot has happened since 1925" by Neil. Moralee is licensed under CC BY-NC-ND 2.0 .

Handling concurrency

Pessimistic Locking

Concurrent locks are rejected

Problems emerge under load

The aggregate pattern

A cluster of objects, Only accessible through the root

Aggregates are a consistency boundary

function addItemToCart(cartId, sku, qty) { // fetch the whole cart const cart = Carts.get(cartId) // make a change cart.addItem(sku, qty) // persist the whole object Carts.put(cart) }

Aggregates reduce locking

Dynamo partitions are a consistency boundary

Optimistic concurrency

class Book { checkOut (userId) { this.checkOutBy = userId; this.version ++; } updateTitle (newTitle) { this.title = newTitle; this.version ++; } }

Optimistic concurrency

function checkOutBook (bookId, userId) { const book = BookRepository.get(bookId); book.checkOut(userId); // this throws a ConcurrencyError; }

Optimistic locks with DynamoDB

Dynamo DB has in-built support for optimistic concurrency control

Inserting a new cart

{ Item: { pk: cart-123, sk: __cart, version: 0, }, ConditionExpression: "attribute_not_exists(pk)", }

Updating a cart

Update: { Key: { pk: cart-123, sk: __cart, }, UpdateExpression: "ADD version :inc", ConditionExpression: "version = :prev", ExpressionAttributeValues: { ":inc": 1, ":prev": 0, }, }

Aggregates balance safety and performance

Strong consistency within aggregates

Eventual consistency between aggregates

Consistency is for decision making

Small is beautiful

Finding aggregates in the library

Is our aggregate the book?

Our aggregate is the loan

Aggregates and view models

Use projections to maintain views

Dynamo Change-streams FTW!


"Time Machine Clockwork" by Pierre J. is licensed under CC BY-NC-SA 2.0 .

What is cohesion?

Cohesion is the flip side of coupling

Cohesion is intra-dependence

Coupling is inter-dependence

Why do utils packages suck?

Utils packages lack cohesion

Reuse is coupling

Bounded contexts

Bounded contexts are conceptual boundaries

Decide what's in and what's out

Borrowing context

Catalogue context

Search context

Context maps

Putting it all together

Deployment boundary

Things that change together ship together

Deployment boundary

  • Find boundaries that align to reasons for change
  • Remember that reuse is coupling

Temporal Boundary

Do the minimum work per-request

Conceptual boundary

What do you need to hold in your head?

Conceptual boundary

A single service might have multiple contexts

Conceptual boundary

  • Look for processes
  • Don't model around nouns

Consistency boundary

What's the smallest unit of correctness?

Consistency boundary

  • Use aggregates to make consistency explicit
  • Use eventual consistency between aggregates


Find me on Twitter
Find slides on Github
Read my blog
Read my book