What I Wish I Knew When I Started Designing Systems (Jakub Nabrdalik)

Discover the essential design principles for building scalable and resilient systems, and learn how to avoid common pitfalls with expert speaker Jakub Nabrdalik's presentation on designing systems.

Key takeaways
  • Don’t split a microservice too early, as this can lead to too many small services.
  • Events are key in microservices, and event-driven design can help reduce coupling.
  • Reactive systems are essential for handling high-frequency requests without a single point of failure.
  • Developers must understand how to implement retries, fallbacks, and circuit breakers.
  • Observability is crucial in complex distributed systems, allowing for troubleshooting and optimization.
  • A service should be designed to be a vertical slice (i.e., focused on a specific process or domain) rather than a horizontal slice (i.e., composed of multiple processes or domains).
  • Microservices should be designed with a singular responsibility and a clear boundary.
  • Communication between microservices should be defined and standardized.
  • Events are used for communication and for ensuring eventual consistency.
  • Distributed transactions are not suitable for high-performance distributed systems.
  • Androidville made the mistake of initially having many small services, while a monolithic architecture with a single database would have been more efficient.
  • As a system becomes more complex, operations become more difficult, but a single point of control (e.g., message broker) can help.
  • In a reactive system, you want to maintain a single source of truth, as updates should occur atomically.
  • Systems should be designed with eventually consistent data, as strong consistency is not required for all operations.
  • Distributed systems require careful consideration of the data’s flow and consistency, as well as the inverse of consistency (partition tolerance).
  • Microservices should be tested in isolation, with end-to-end testing being difficult due to the distributed nature.
  • Confidence in the system can only be gained through constant testing and monitoring.
  • Higher-level abstractions, such as sagas and event sourcing, can simplify the complexity of distributed systems.