← System design basics for freshers and junior engineers

Lesson 4 of 5

Reliability, observability and low-level design

2 min read

Designing for failure

Everything fails eventually: servers, networks, dependencies.

  • Redundancy: multiple instances across availability zones; no single point of failure.
  • Timeouts on every network call; retries with exponential backoff and jitter; only retry idempotent operations.
  • Circuit breaker: stop calling a failing dependency for a while; return a fallback.
  • Graceful degradation: if recommendations are down, still show the page without them.
  • Backups and tested restores; define RPO (how much data you can lose) and RTO (how fast you must recover).

Observability

  • Metrics (rate, errors, duration: "RED"), logs (structured with request ids), traces across services.
  • SLIs/SLOs: "99.9% of redirects succeed in under 100 ms over 30 days". The error budget decides how fast you can ship risky changes.

Security in designs

Authentication at the gateway, authorisation in each service, encryption in transit (TLS) and at rest, secrets in a vault, rate limiting, audit logs for sensitive actions.

Low-level design (LLD) rounds

Some companies ask you to design classes for a parking lot, library, elevator, splitwise or a job portal module. They check object-oriented thinking:

  1. Identify entities (nouns) and behaviours (verbs).
  2. Define classes, their fields and methods, and relationships (has-a, is-a).
  3. Apply SOLID: single responsibility, open/closed (extend without editing), Liskov substitution, interface segregation, dependency inversion.
  4. Use patterns where they fit: Strategy (pricing rules), Factory (creating vehicles or notifications), Observer (notify on status change), Singleton (sparingly), State (order status transitions).
  5. Handle concurrency where needed (two people booking the last slot).
java
interface PricingStrategy { int price(Ticket t, Instant exit); }
class HourlyPricing implements PricingStrategy { ... }
class WeekendPricing implements PricingStrategy { ... }

class ParkingLot {
  private final List<Floor> floors;
  private final PricingStrategy pricing;
  Ticket park(Vehicle v) { /* find a free spot of the right size, lock it, issue a ticket */ }
  Receipt exit(Ticket t) { /* free the spot, compute the price with the strategy */ }
}

Check yourself

  • Why add jitter to retries?
  • What is an SLO, and what is an error budget used for?
  • Sketch the classes for a library management system.

Sign up free to save your progress.

Reliability, observability and low-level design · System design basics for freshers and junior engineers · HireSol