From requirements and diagrams to scalable, reliable software architecture.
Learn system design as a sequence of decisions, using a small learning platform as the running example.
Functional requirements describe behavior users need; non-functional requirements define qualities and constraints such as latency, accessibility, security, capacity, and recovery.
High-level design explains system boundaries, data flow, dependencies, and major tradeoffs; low-level design specifies components, interfaces, data models, algorithms, and failure handling.
A capacity estimate converts product assumptions into requests per second, concurrency, stored bytes, and network throughput. Ranges and peak factors are more honest than false precision.
A monolith deploys as one unit, a modular monolith enforces internal boundaries within that unit, and microservices deploy bounded capabilities independently. Team and operational needs should drive the choice.
A stateless service can handle the next request on any equivalent instance using external state; a stateful service owns durable or session state that affects placement, scaling, and recovery.
In event-driven systems, producers publish facts that happened and consumers react independently. Pub/sub reduces direct coupling but introduces retries, ordering, duplication, and observability work.
Serverless runs functions or managed services on demand while the provider handles much of the infrastructure. You still own code, data, permissions, cost behavior, observability, and recovery.
Vertical scaling gives one machine more resources; horizontal scaling adds machines. The second needs distribution, coordination, and state design, so it is not automatically better.
Availability measures whether a service can be used, reliability measures correct behavior over time, and fault tolerance is the design ability to continue when a component fails.
CAP says that during a network partition, a distributed system must choose between always returning a response and guaranteeing every response reflects the latest successful write. It does not mean choosing only two properties forever.
A load balancer distributes requests across healthy targets; consistent hashing keeps most key-to-node assignments stable when nodes change, which helps partitioned caches and stateful routing.
Replication copies data; partitioning divides it; sharding commonly means application-visible horizontal partitions across database nodes. Clear terminology matters more than labels.
Latency is time per operation, throughput is completed work per time, and a bottleneck is the constrained resource that currently limits the system. Improving one metric can worsen another.
A cache trades freshness and complexity for lower latency and load. A safe design states the cache key, owner, lifetime, invalidation event, and behavior on a miss or stale value.
A CDN serves cacheable content near users, an edge layer runs limited logic near the network boundary, a reverse proxy routes and protects origins, and an API gateway applies API-specific policies.
Queues absorb bursts, rate limits protect finite capacity, and backpressure tells producers to slow down. Together they bound work instead of hiding overload until failure.
SOLID guides change-friendly responsibilities and dependencies; DRY reduces harmful duplication; KISS favors understandable designs; YAGNI delays speculative capability. These are lenses, not absolute laws.
UML is a shared visual vocabulary. Use the smallest diagram that answers a question: class for structure, sequence for interaction over time, state for lifecycle, and component for boundaries.
A design pattern names a recurring design tradeoff and arrangement of responsibilities; it is useful when the forces match, not as decoration for simple code.
Authentication proves identity, authorization limits actions, TLS protects data in transit, and disaster recovery restores service and data after a severe failure. These controls cover different risks and must be tested together.
Distributed-system tests must cover boundaries and time: retries, duplicates, delay, reordering, partial failure, clock assumptions, and recovery—not only happy-path responses.