4 minute read

Domain Model: Your Business Blueprint

A domain model is a package of classes and interfaces representing your business domain in code. This software model serves as the custom language your systems use to communicate and store data.

As the central representation of your business, your domain model is your business. Your software practice’s success critically depends on this model’s quality and implementation.

When done correctly, the representation exists in one place and enables compact binary wire communication. It supports polyglot development and in certain cases is ‘zero-copy’.

Achieving these qualities creates efficient software—making modifications inexpensive for engineers while making the software up to 10x faster than alternatives like JSON.

Prior Art and Books

Many books cover Domain Driven Design. The Larman UML design book captures not just the domain model but the entire system design process—from business cases through system design and unit testing.

Applying UML and Patterns by Craig Larman

Chapter 6 provides an excellent introduction to Use Case design modeling. Start by writing business cases as simple steps: “user does X, system responds Y.” The X’s and Y’s become your nouns and verbs—these relationships form your domain model.

You’ve succeeded when you have zero “synthetic” objects—types with no direct business domain mapping. This creates a ‘clean’ software model. Synthetic types should only exist to improve latency.

Domain Model Accuracy

Accuracy is critical to success.

The inheritance vs. composition question is paramount. Always prefer composition. True inheritance relationships (like “Truck is a Vehicle”) are rare and rarely important enough to dictate your model’s shape. In banking there’s no universal “base account” everything inherits from. Instead things have accounts attached through composition.

Domain Model as Data

Your domain model eventually becomes data stored in a database, typically represented first in an Entity Relationship Diagram (ERD).

The ERD captures relationships as data. Key concerns include:

  • Audit trails on every table (who edited and when)
  • Keys for every piece of data
  • Synthetic primary keys for storage efficiency

Temporality in ERD Design

Consider temporality and bi-temporality when modeling data. Without temporality you must audit data in separate tables—doubling cost and tripling complexity.

Domain Model Management

Version the domain model as an exclusive project—one of your most critical artifacts. Never split it into multiple packages; use package hierarchies instead.

Include no other dependencies. The domain model must be purely software structures.

Version carefully. Never make backwards-incompatible changes since any system may use prior versions. Form a domain model committee of management, business owners and senior engineers to review changes.

Domain Model Distribution

Every project should build domain model artifacts and check for problems at build time.

Create a main branch for tested and approved changes. All projects reference this main branch.

When you add a field to a service, it instantly propagates without team interaction. This creates seamless upgrades for your domain.

Consider adding Confluent schema registry alongside the GIT approach as needed.

Protocol Buffers

Protocol Buffers from Google should be your preferred format.

The approach captures both domain model and efficient binary implementation in one representation. This is a powerful combination that has proven successful at scale.

Organizations using domain models with Protobufs gain significant advantages. The decision made at project start impacts costs over the software’s lifetime.

Cost of Change

How difficult is adding a field? This directly measures your design quality.

Adding fields is the most common operation. Adding new types comes second.

Test your design: How expensive is adding a field? How many files and projects need deployment? With one tidy Protobuf domain model, these costs are minimized.

Software as a Design Game

Software design offers profound leverage. Small investments done correctly reap years of benefits after production.

Once in production, changes take 10x more effort than during development. Business cases connected to your domain model grow and each requires re-testing. This increases both cost and risk.

Working with Different Formats

When teams use different technologies (C++ vs Java), Protobufs can communicate with both. It’s important to evaluate frameworks thoroughly, considering:

  • Real business models have 5-30 fields (closer to 30 for important structures)
  • Most fields are null 99% of the time
  • Performance characteristics change dramatically with null fields
  • The need for translation layers between different formats

Shared Foundations

Developers benefit from shared foundations and common understanding of software principles. This reduces repeated discussions and helps teams move forward efficiently.

Large companies often document these principles extensively. Smaller businesses can achieve similar benefits by establishing clear technical standards early.

Building a Domain Model

Building a domain model requires understanding:

  • Cost differences between Protobufs, Flatbuffers and JSON
  • Binary vs. non-binary formats
  • Schema benefits and validation
  • Performance implications at scale

Latency Considerations

For single messages, format differences are minimal.

But sending bulk messages (e.g., 1,000,000) can significantly impact performance. With finance pipelines needing sub-5-second real-time reporting, format choice becomes critical.

This demonstrates “shift-left performance”—accounting for latency and cost at the earliest point possible.

Conclusion

Domain model represents an opportunity at project start.

A small investment in organized, fast communication reaps years of benefits. The setup might take a day or two but pays dividends over time.

While corners must be cut when starting any project, invest in a domain model—the benefits more than pay for the investment.

Best Practices Summary

  1. Use Protocol Buffers for efficient binary communication
  2. Prefer composition over inheritance in your domain design
  3. Version your domain model carefully in a dedicated project
  4. Never make backwards-incompatible changes to production models
  5. Consider temporality in your data design from the start
  6. Test the cost of change - adding a field should be simple
  7. Build once, use everywhere - reference a single main branch
  8. Plan for scale - consider bulk operations and latency requirements

Resources

Updated: