Compile Ready
All low level design problems
Low Level Design/Beginner/Core Systems

Design a Library Management System

Members, books, copies, holds, and fines — the classic CRUD-heavy modelling exercise done cleanly.

Beginner 45m interview 14m read Medium frequency Popularity 78
Repository Strategy Observer Amazon Oracle Microsoft

Problem Statement

Design the object model for a Library Management System used by a public or university library. The system must catalog books, track physical book copies, register members, let members search the catalog, borrow and return copies, calculate fines for overdue returns, and maintain reservation queues when popular titles are unavailable.

The interview focus is the domain model and the seams around policy: searching, lending rules, fines, reservations, and notifications. A clean answer separates the bibliographic record from each physical copy, keeps loan state consistent, and avoids turning the service layer into a pile of conditional logic.

Business context

Library Management is a beginner-friendly but realistic LLD problem because it mixes CRUD-like catalog data with state transitions that must be correct: a copy cannot be loaned twice, a member cannot exceed the loan limit, and a returned copy may need to satisfy the oldest reservation before becoming generally available.

Interviewers use this problem to evaluate whether you can model Book versus BookCopy, use Repository-like collections for lookup, apply Strategy to catalog search, and apply Observer to reservation notifications without over-engineering the solution.

Functional Requirements

  • Store bibliographic books with ISBN, title, authors, and subject.

  • Track physical book copies by barcode and status: available, loaned, reserved, or lost.

  • Register members and enforce a maximum number of open loans per member.

  • Search the catalog by title, author, or subject.

  • Borrow an available copy of a requested ISBN and create a loan with a due date.

  • Return a borrowed copy, close the loan, and calculate an overdue fine.

  • Allow members to reserve a book when copies are unavailable or currently loaned.

  • Notify the next reserved member when a returned copy is held for them.

Non-Functional Requirements

State correctness

A copy must never be both available and loaned. All transitions go through BookCopy methods that validate the current status.

Extensibility

New search modes, fine policies, and notification channels should be additive. The lending workflow should not need a rewrite for each new rule.

Interactive latency

Catalog search and borrow should be fast enough for a librarian desk workflow. The reference solution uses in-memory scans; production would add indexes.

Fair reservations

Reservations for the same ISBN are served FIFO so the earliest waiting member gets the next returned copy.

Thread safety at hot spots

Copy status and member open-loan counts are synchronized so two desks cannot lend the same copy or exceed a member limit.

Requirement Clarification

QIs **Book** the same as a physical copy?

No. Book is the bibliographic record identified by ISBN. BookCopy is a physical item with a barcode and status. Multiple copies can point to the same book.

QHow long is a loan?

Assume a fixed 14-day loan period in the base design. A production design can extract this into a policy object.

QCan members reserve a specific barcode?

For the base design, reservations are at the ISBN level, not at the barcode level. The next returned copy of that ISBN can satisfy the oldest reservation.

QDo fines block future borrowing?

The reference solution calculates and returns the fine amount on return. Blocking behavior is a policy extension that can consult a member account balance.

QDo we need staff roles, payments, or a REST API?

No for the core LLD. Model the domain and service behavior first; staff auth, payment collection, and HTTP controllers are adapters around this model.

UML Class Diagram

Rendering diagram…
The design separates catalog data, physical copy state, member loan limits, and service orchestration. **Catalog** behaves like an in-memory repository, **SearchCriteria** is the search strategy seam, and **ReservationNotifier** is the observer boundary.

Sequence Diagram

Rendering diagram…
Borrow is a copy-level check-then-mark transition. Return closes the loan, computes the fine, then either releases the copy or reserves it for the next waiting member and notifies through the observer.

Entity Identification

Book

Bibliographic record for a title. It carries ISBN, title, authors, and subject, but has no availability state.

isbntitleauthorssubject

BookCopy

Physical copy identified by barcode. Owns the status transition methods so callers cannot casually flip between available, loaned, reserved, and lost.

barcodebookstatus

CopyStatus

Enum describing a copy lifecycle: AVAILABLE, LOANED, RESERVED, and LOST.

AVAILABLELOANEDRESERVEDLOST

Member

Registered library user. Tracks open loans and enforces the per-member loan limit through canBorrowMore and addLoan.

idnamemaxOpenLoansopenLoans

Catalog

In-memory repository for books and copies. It answers catalog search queries and finds an available copy for an ISBN.

bookscopies

SearchCriteria

Strategy interface for matching a book during catalog search. Concrete criteria handle title, author, and subject queries.

matches(book)

Loan

Record of one borrowing session: copy, member, issue date, due date, and optional return date.

copymemberissueDatedueDatereturnedDate

Reservation

A waiting member's hold on a book. It records the book, member, creation time, and active flag, then becomes fulfilled when a copy is held.

bookmembercreatedAtactive

FineService

Fine calculation policy. It multiplies overdue days by a configured daily fine and returns zero for on-time returns.

dailyFine

ReservationNotifier

Observer boundary for notifying a member that a reserved copy is ready. Email, SMS, app push, or test spies can implement it.

notifyReady(member, copy)

LibraryService

Application service and aggregate coordinator. It borrows, returns, reserves, tracks open loans by barcode, and owns reservation queues by ISBN.

catalogfineServicenotifieropenLoansByBarcodereservationsByIsbn

Design Patterns Used

Repository

Catalog centralizes book and copy storage behind add, search, and availability lookup methods. The service asks the repository-like object for data instead of walking raw collections everywhere.

Strategy

SearchCriteria lets title, author, and subject searches vary independently of Catalog.search. Adding ISBN or keyword search is a new criteria class, not an edit to the catalog loop.

Observer

ReservationNotifier decouples the reservation workflow from the notification channel. Returning a copy triggers notifyReady, while email, SMS, or app push remain outside the domain.

Step-by-Step Design

  1. 1Separate the title record from the copy state

    Model Book as immutable catalog metadata and BookCopy as the mutable physical item. The barcode belongs to the copy; ISBN belongs to the book.

    public final class BookCopy {
        private final String barcode;
        private final Book book;
        private CopyStatus status = CopyStatus.AVAILABLE;
    
        public synchronized void markLoaned() {
            requireStatus(CopyStatus.AVAILABLE);
            status = CopyStatus.LOANED;
        }
    }
  2. 2Make catalog lookup repository-like

    Catalog owns the collections and exposes meaningful operations: search and findAvailableCopy. This keeps data access out of LibraryService and makes a database-backed repository a clean future replacement.

  3. 3Use strategies for search criteria

    The catalog does not switch on query type. It accepts a SearchCriteria and asks whether each book matches. Title, author, and subject searches are independent strategies.

    interface SearchCriteria {
        boolean matches(Book book);
    }
    
    final class TitleCriteria implements SearchCriteria {
        public boolean matches(Book book) {
            return book.getTitle().toLowerCase(Locale.ROOT).contains(token);
        }
    }
  4. 4Borrow by locking the copy and validating the member limit

    LibraryService.borrow asks the catalog for an available copy, synchronizes on that copy, validates the status and member limit, marks the copy loaned, creates a Loan, indexes it by barcode, and adds it to the member.

    synchronized (copy) {
        if (copy.getStatus() != CopyStatus.AVAILABLE) {
            throw new IllegalStateException("Copy was borrowed by another request");
        }
        if (!member.canBorrowMore()) {
            throw new IllegalStateException("Member cannot borrow more books");
        }
        copy.markLoaned();
    }
  5. 5Return closes the loan before changing copy availability

    returnCopy removes the open loan, closes it with the return date, updates the member's open-loan set, calculates the fine, then decides what happens to the copy.

  6. 6Serve reservations through a FIFO queue and an observer

    Reservations are grouped by ISBN. On return, the service polls the queue; if a reservation exists, the copy becomes RESERVED, the reservation is fulfilled, and ReservationNotifier is called.

    if (next == null) {
        copy.markAvailable();
    } else {
        next.fulfill();
        copy.markReserved();
        notifier.notifyReady(next.getMember(), copy);
    }

Complete Java Implementation

Loading…

Explanation of Every Class

Book

Immutable bibliographic metadata. It validates ISBN, defensively copies the authors list, and exposes read-only getters so catalog records are not mutated accidentally.

BookCopy

Represents one physical item with a barcode and status. Synchronized transition methods enforce status rules for loaning, reserving, making available, and marking lost.

CopyStatus

Enum for the copy lifecycle: AVAILABLE, LOANED, RESERVED, and LOST. It keeps state values explicit and avoids magic strings.

Member

Stores member identity, maximum loan count, and an internal set of open loans. Synchronized methods protect the loan-limit invariant.

Catalog

In-memory repository for Book and BookCopy objects. It adds records, searches books with a supplied strategy, and finds the first available copy for an ISBN.

SearchCriteria

Strategy interface used by Catalog.search. Each implementation decides whether a book matches a particular query style.

TitleCriteria

Case-insensitive title search strategy. It lowercases the search token and checks whether the book title contains it.

AuthorCriteria

Case-insensitive author search strategy. It scans all authors of a book and succeeds when any author contains the token.

SubjectCriteria

Case-insensitive subject search strategy. It keeps subject filtering separate from title and author matching.

Loan

Borrowing session record. It knows the copy, member, issue date, due date, and return state; close prevents double returns.

Reservation

A member's waitlist entry for a book. It captures creation time for ordering and transitions from active to fulfilled exactly once.

ReservationNotifier

Observer interface called when a returned copy is reserved for the next waiting member. Implementations can send email, SMS, app push, or test notifications.

FineService

Overdue fine calculator. It validates the configured daily fine and charges only for days after the loan due date.

LibraryService

Coordinates the application flow. It borrows copies, returns copies, creates reservations, indexes open loans by barcode, and moves returned copies to either available or reserved.

Dry Run

Sample input

Catalog has Clean Code with ISBN ISBN-1 and one copy C1. Daily fine is 5. Member M1 can borrow 2 books. Member M2 reserves the title while C1 is loaned.

StepActionCatalog and copy stateLoan stateReservation stateResult
1addBook and addCopy(C1)Book indexed; C1 AVAILABLENo open loansNo reservationsCatalog ready
2search TitleCriteria cleanBook matches title searchNo open loansNo reservationsSearch returns Clean Code
3borrow ISBN-1 by M1 on Jul 1C1 moves to LOANEDLoan L1 due Jul 15No reservationsBorrow succeeds
4reserve book by M2C1 remains LOANEDL1 still openQueue ISBN-1 contains R1Reservation recorded
5return C1 on Jul 18C1 moves to RESERVEDL1 closes; fine is 15R1 fulfilledM2 notified that C1 is ready

The run shows the core invariants: search is read-only, borrow changes the copy to LOANED, a reservation waits by ISBN, and return computes three overdue days of fine before reserving the copy for the next member.

Complexity Analysis

OperationTimeSpaceNote
Catalog.searchO(B × A)O(R)B books, A authors per book for author search, R matching results.
findAvailableCopyO(C)O(1)Linear scan over copies in the in-memory reference catalog.
borrowO(C)O(1)Dominated by finding an available copy; loan insertion and member update are constant time.
returnCopyO(1)O(1)Open-loan lookup, fine calculation, and reservation queue poll are constant time.
reserveO(1)O(1)Append to the per-ISBN queue.

The reference solution favors clarity over indexing. A production repository would maintain maps by ISBN, title tokens, author tokens, and barcode so search and availability avoid full scans.

Extensibility

Database-backed repositories

Replace Catalog with BookRepository and CopyRepository implementations without changing the lending flow. Keep the service dependent on repository operations, not storage details.

More search strategies

Add IsbnCriteria, KeywordCriteria, or composed criteria. Catalog.search still receives a SearchCriteria and does not branch by type.

Flexible lending policy

Extract loan duration, renewal limits, and fine rules into policy objects when requirements differ for students, faculty, or premium members.

Notification channels

Implement ReservationNotifier with email, SMS, push notifications, or a fan-out composite. The return flow remains unchanged.

Alternative Designs

Full repository layer per aggregate

Create BookRepository, CopyRepository, LoanRepository, and ReservationRepository interfaces, then inject concrete in-memory or SQL implementations.

Tradeoffs

Closer to production and easier to persist, but more boilerplate for a beginner interview. Start with Catalog unless the interviewer asks about storage.

Policy objects for all rules

Extract LoanPolicy and FinePolicy so duration, borrowing eligibility, renewals, and fines vary by member type.

Tradeoffs

Very extensible, but can distract from the core model if introduced before the requirements demand it.

Event-driven reservation fulfillment

Publish a CopyReturned event and let a reservation handler reserve the copy and notify the member asynchronously.

Tradeoffs

Improves decoupling and reliability at scale, but introduces eventual consistency and more infrastructure than needed in the base design.

Common Mistakes

  • ×

    Treating Book and BookCopy as the same object, which makes multiple physical copies impossible to model cleanly.

  • ×

    Representing copy status as strings and updating it directly from the service instead of using transition methods.

  • ×

    Hard-coding title, author, and subject branches inside Catalog.search instead of using SearchCriteria strategies.

  • ×

    Forgetting to close the member's open loan on return, so the member permanently loses borrowing capacity.

  • ×

    Making returned copies immediately available even when there is an existing reservation queue.

  • ×

    Calling notification code directly through an email class instead of depending on ReservationNotifier.

  • ×

    Ignoring concurrency around the copy status check and mark operation.

Follow-up Interview Questions

QHow would you make catalog search faster?

Maintain indexes in the repository: ISBN to book, normalized title token to books, author token to books, and ISBN to available-copy queues. The domain model can stay the same.

QHow do you support renewals?

Add a renewal count and a LoanPolicy that checks whether the loan is open, not reserved by another member, and below the renewal limit before extending the due date.

QWhat happens if two librarians try to borrow the same copy?

The service synchronizes on the candidate BookCopy and rechecks the status before markLoaned. Only one request can complete the transition.

QHow would you collect fines?

Keep FineService responsible for calculation, then add a payment adapter or account ledger outside the core loan-closing flow. Calculation and collection are separate concerns.

QHow would you notify many channels at once?

Implement ReservationNotifier as a composite that invokes email, SMS, and app push observers. The return flow still depends on one interface.

Production Considerations

Persistence and transactions

Store books, copies, loans, members, and reservations in a database. Borrow and return should be transactional so copy status, loan rows, and reservation rows stay consistent.

Indexes

Add indexes on ISBN, barcode, normalized title, author, subject, and reservation queue position to avoid scanning as the library grows.

Concurrency control

Use row-level locks or optimistic version columns on BookCopy and Member to prevent double lending across multiple app instances.

Auditability

Record every loan, return, renewal, fine calculation, and status change with actor and timestamp. Libraries need dispute resolution and compliance history.

Operational notifications

Make notifications retryable and idempotent. A copy should not be released to the general pool just because an email provider is temporarily down.

What Interviewers Look For

  • Did you clearly separate Book from BookCopy?

  • Are copy status transitions guarded by the domain object rather than scattered assignments?

  • Is catalog lookup isolated behind repository-style methods?

  • Can new search criteria and notification channels be added without editing the core flow?

  • Do returns respect FIFO reservations before marking a copy available?

  • Did you discuss concurrency for the borrow path?

Quiz

0/5 answered

  1. 1.Why does the model need both **Book** and **BookCopy**?

  2. 2.Which part of the reference solution demonstrates Strategy?

  3. 3.Why is **ReservationNotifier** an interface?

  4. 4.What should happen when a loaned copy is returned and a reservation queue exists?

  5. 5.What is the main complexity bottleneck in the reference implementation?

Practice Variants

Add renewals

Beginner

Allow a member to renew an open loan when no other member has reserved the book. Add renewal limits and update due-date logic cleanly.

Add member tiers

Intermediate

Students, faculty, and guests have different loan limits, loan durations, and fine caps. Extract the policy without bloating LibraryService.

Add branch libraries

Advanced

Support multiple branches, copy transfers, and reservations that can prefer a member's home branch before searching globally.

Flashcards

Cheat Sheet

Entities: Book, BookCopy, CopyStatus, Member, Catalog, SearchCriteria, Loan, Reservation, FineService, ReservationNotifier, LibraryService.

Patterns: Repository through Catalog, Strategy through SearchCriteria implementations, Observer through ReservationNotifier.

Borrow flow: find available copy by ISBN → lock copy → check member limit → mark loaned → create Loan → index by barcode → add to member.

Return flow: remove open loan → close loan → remove from member → calculate fine → poll reservation queue → reserve and notify or mark available.

Invariants: one status per copy; no loan without an available copy; member loan limit enforced; reservations served FIFO.

Complexity: search O(B×A), find available copy O(C), borrow O(C), return O(1), reserve O(1) in the in-memory reference design.

Extend: add repositories for persistence, policies for loan/fine rules, more SearchCriteria classes, and notifier implementations for real channels.

References

  • BookPatterns of Enterprise Application Architecture — RepositoryMartin Fowler
  • BookHead First Design Patterns — Strategy and ObserverFreeman & Robson
  • DocsRefactoring Guru — Observer Pattern