Chapter 1 – Interview Questions: Thinking in Systems

Practice answering these out loud before revealing the sample answers.

Q1: How do you approach designing a new system from scratch?

So honestly, the first thing I do is resist the urge to jump into tech choices. I'd start by really understanding the problem — who are the users, what are the core use cases, and what does success look like? I'll sketch out the boundaries of the system, figure out the inputs and outputs, and identify the main entities.

Then I'd think about the non-functional requirements — like do we need five-nines uptime, or is this an internal tool where some downtime is fine? The way I think about it is: constraints shape the design more than features do. Once I've got that clarity, I'll draft a high-level component diagram, identify the data flows, and only then start picking technologies that fit the constraints.

Key Points (what interviewers look for):

  • Starts with requirements, not technology
  • Identifies actors, use cases, and boundaries
  • Considers non-functional requirements early
  • Iterates from high-level to detailed design

Q2: What trade-offs have you made in past projects?

One that comes to mind — I was working on a real-time analytics dashboard, and we had to choose between strong consistency and low latency. We went with eventual consistency because, honestly, showing data that's 2-3 seconds stale was totally acceptable for our users, but adding 500ms of latency to every request was not.

The way I think about trade-offs is: every decision has a cost. I'd always try to make the trade-off explicit and document why we chose one path. I've also traded development speed for technical debt — like shipping a monolith first to validate the product, knowing we'd refactor later. The key is being intentional about it rather than accidentally painting yourself into a corner.

Key Points:

  • Gives a concrete, specific example
  • Explains the reasoning and constraints
  • Shows awareness that trade-offs are intentional decisions
  • Mentions documenting decisions for the team

Q3: How do you estimate capacity for a new service?

I'd start with the expected traffic — like how many requests per second at peak? Then I'd work backwards from there. So basically, if we're expecting 10,000 requests per second and each request takes about 50ms to process, I can estimate how many instances I need just from that math.

But honestly, I also pad those numbers. I'd typically plan for 3-5x the expected peak because traffic spikes are real. I also think about storage growth — how much data per user per day, multiply by expected users, project out 6-12 months. The way I think about it is: estimation is about getting the order of magnitude right, not being precise. Am I going to need 2 servers or 200? That's the question that actually matters early on.

Key Points:

  • Uses back-of-envelope math with concrete numbers
  • Accounts for peak vs. average traffic
  • Plans headroom for spikes
  • Focuses on order of magnitude, not false precision

Q4: What non-functional requirements matter for a payment system?

Oh, payments — this is where you can't cut corners. The big ones I'd focus on: first, consistency. You absolutely cannot have a situation where money is debited but the order isn't recorded. So you need strong transactional guarantees, probably ACID compliance for the critical path.

Second, durability — every transaction must be persisted, no data loss, ever. Third, availability with graceful degradation — if a downstream provider is down, queue the transaction rather than losing it. Fourth, security — PCI compliance, encryption at rest and in transit, audit logs for everything. And honestly, idempotency is huge — network retries happen, and you cannot charge someone twice. I'd also add observability — you need to be able to trace every dollar through the system.

Key Points:

  • Prioritizes consistency and durability over raw performance
  • Mentions idempotency (critical for payments)
  • Addresses security and compliance requirements
  • Thinks about failure modes and graceful degradation

Q5: How do you decide when a system is 'good enough'?

This is something I've learned the hard way, honestly. Early in my career I'd over-engineer everything. Now the way I think about it is: does this system meet the current requirements with reasonable headroom for the next stage of growth — not the stage five years from now?

So basically, I'd ask: are we meeting our SLAs? Can the team maintain and extend this without heroics? Is the code understandable to someone new? If yes to all three, it's good enough. I'm a big believer in iterative improvement — ship something solid, observe how it behaves in production, then improve based on real data rather than hypothetical scenarios. Premature optimization is real, but so is premature architecture. You don't need event sourcing and CQRS for a CRUD app with 100 users.

Key Points:

  • Balances pragmatism with quality
  • Defines concrete criteria (SLAs, maintainability, clarity)
  • Advocates iterative improvement over upfront perfection
  • Aware of over-engineering as a real risk