Design a Library Management System

The gentle classic that tests one big idea: a Book is not a BookCopy. Catalog vs inventory, loans, reservations and fines.

LLDOODentity-modeling

Scope it first

"Members search the catalog, borrow and return physical copies, reserve books that are out, and pay late fines. Librarians manage inventory. Single branch — multi-branch as a follow-up. OK?"

This is the friendliest LLD classic, which is exactly why it's asked: with no concurrency fireworks to hide behind, the grading falls entirely on entity modeling — and one distinction decides the interview.

The one big idea: Book vs BookCopy

"1984 by Orwell" and "the physical copy with barcode #4471" are different things. The catalog entry (title, author, ISBN) exists once; the library owns five copies of it, each with its own condition, shelf and loan history:

  • Search and reservations are about the Book ("is 1984 available?" = does any copy stand free).
  • Borrowing, returning, damage and fines are about the BookCopy (which physical object is in whose hands).

Merge them and everything breaks: five copies means five duplicate title rows (the normalization sin), and "who has the book?" has no answer because the book isn't a thing anyone can hold. This is the same item-vs-instance split as BookMyShow's Seat vs per-show SeatState and a flight vs a specific departure — interviewers reuse the test endlessly because so many candidates fail it.

Entities & relationships

The supporting decisions worth saying out loud:

  • Loan is its own entity, not fields on Member or Copy — it's the relationship with history (who, what, when, due, returned). Past loans are the audit trail; fines compute from them. Whenever two entities relate with attributes, the relationship is a class.
  • Reservation targets the Book, not a copy — the member wants any copy of 1984; binding to copy #4471 would make them wait for that one while #4472 sits free. A FIFO queue per book; on return, the head reservation converts to a hold.
  • BookCopy.status is a small state machine (ON_SHELF → ON_LOAN → ON_SHELF, with RESERVED/LOST branches) — guard transitions; "checkout a LOST copy" should be unrepresentable (the State discipline).
  • Fines as records, not arithmetic on the fly — a Fine is created at return-time (days late × rate via a Strategy — children's books may differ from DVDs), then persists until paid. Money facts are append-only.

A BookCopy is a small state machine — here it is. Walk a normal loan (Shelf → OnLoan → Shelf), then the reservation path where a return skips the shelf and goes straight to a hold (returnToHold); then try an illegal move — a checkout while it's already on loan — and watch the copy simply refuse it.

Book copy lifecycletime O(1) per eventspace O(states)
checkoutreturnreturnToHoldpickupexpireloseShelfOnLoanHeldLost
events:checkoutreturnToHoldpickupreturn

1/5Start in Shelf. Each event is handled by the current state — the State pattern moves this branching out of one giant switch and into the state objects themselves.

state = Shelf

Think it through like the interview

Think it through: Design a Library Management SystemLLD Classic — entity modeling0/5 stages

PROBLEMMembers search a catalog, borrow and return physical copies, reserve books that are out, and pay late fines. Librarians manage inventory. Design the classes.

  1. 1

    Scope, then find the trap

    This problem is famously 'easy'. So what is it actually grading?

  2. 2

    Type vs instance

    '1984 by Orwell' and 'the copy with barcode #4471' — same object?

    unlocks after the stage above
  3. 3

    Relationships with history become classes

    Where do dueDate and returnedAt live — on Member? On BookCopy?

    unlocks after the stage above
  4. 4

    Attach things at the right level

    A reservation — does it point at the Book or at a BookCopy?

    unlocks after the stage above
  5. 5

    Walk the busiest scenario

    Asha returns 1984 three days late, and Rahul has a reservation. Narrate every object touched.

    unlocks after the stage above

Walk a scenario

"Asha borrows 1984": search finds the Book with availableCopies() = 2 → librarian scans copy #4471 → Library.checkout(asha, copy4471) validates the business rules (member in good standing? under the 5-loan limit? no unpaid fines over ₹100?) → copy ON_SHELF → ON_LOAN, a Loan with dueDate = +14 days. Return three days late → Loan closes, fine strategy creates a ₹15 Fine on Asha → copy's status checks the reservation queue: Rahul reserved 1984, so ON_SHELF is skipped for RESERVED, Rahul gets a notification and 48 hours to collect, expiry releases it (TTL self-healing, the library edition).

That late-return path is the busiest flow in the system — worth seeing end to end:

Business-rule placement is the quiet test here: the loan-limit check lives in Library.checkout (it spans member + loans), the status-transition guards live in BookCopy — rules sit with the data they protect (encapsulation), not in one god method.

Practice — level up

A library is inventory + lending: allocate a copy, return it, track who has what for how long. These drills rehearse those moves.

Practice ladder: Inventory & lending0/4 solved

Climb in order — every rung assumes the one above it. Solve on LeetCode, then tick it here; progress is saved on this device.

Warm-up — count what's available

  1. Per-type counters — available copies of each title.

Core — allocate & return specific copies

  1. Reserve / release a specific numbered slot — a book copy.

  2. Borrow → return pairs, with duration (the loan period).

Stretch — state as of a time

  1. Look up a record as of a timestamp — due dates and loan history.