Arriving at Scalability – part 2

Several decisions we’ve made earlier became powerful enablers for our first pass at Scalability.


Queryable Repository

Data reads take time, reading less than everything is always a good idea. Implementing Repositories as queryable allowed us to switch to paged, ordered and generally highly selective views.


Unit of Work

Effectively building small projections for the UI from large datasets was possible due to request-scoped Unit of Work implementation, enabling underlying ORM to read data across multiple Repositories.


Aggregate Roots

Root Aggregate, defined as a cluster of associated objects treated as a unit for the purpose of data changes. By implementing Repositories one per aggregate, we isolated data affected by transactions and avoided deadlocks. With a bit of per-ID synchronization we were able to avoid optimistic concurrency exceptions as well.


Message passing

By integrating message passing early, we were able to move all the writes to backend services and avoid distributed locks in exchange for eventual consistency. Moving the backend services to another machine after this was trivial.


And that’s how by scaling out we were able to get that x100 performance gain, on the cheap. We’ll do it again a few months later by batching, denormalizing the data and embracing Event-Driven SOA.

Arriving at Scalability – part 2

One thought on “Arriving at Scalability – part 2

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s