Bird
Raised Fist0

Online Auction System

LLDmediumInterview freq: medium
Choose your preparation mode4 modes available
🏗️
Online Auction System
Bid, Timer, Winner, Reserve Price, Notification
mediumFinancial and E-Commerce OOPFreq: medium
Prerequisites:Factory PatternObserver Pattern
⚙️
Functional Requirements
  • Allow multiple bidders to place bids concurrently on an auction
  • Maintain highest bid and bidder atomically
  • Enforce reserve price: auction only closes with winner if reserve price met
  • Auction automatically closes when timer expires
  • Notify all bidders asynchronously about bid updates and auction results
  • Support bid withdrawal before auction closes
  • Prevent bids after auction is closed
👤
Use Cases
  • Place a bid on an active auction
  • Start an auction with a reserve price and timer
  • Automatically close auction when timer expires
  • Determine and declare the winner if reserve price met
  • Notify bidders about bid status and auction results
🧑‍💻
Actors
  • Bidder
  • Auctioneer
  • System Timer
  • Notification Service
❓
Clarifying Questions to Ask
  • How many concurrent bidders are expected per auction? (Concurrency level)
  • Should the system support bid increments or proxy bidding?
  • What happens if two bids arrive at the exact same timestamp?
  • Is the reserve price fixed or can it be updated during auction?
  • How precise is the auction timer? Milliseconds or seconds?
  • Should notifications be synchronous or asynchronous?
  • What is the behavior if no bids meet the reserve price?
Out of Scope
✗ Payment processing and escrow
✗ User authentication and authorization
✗ Detailed UI design
✗ Multi-currency support
🔢
Enumerations
enum AuctionStatus
CREATED | ACTIVE | CLOSED
Defines auction lifecycle states explicitly to prevent invalid state transitions and enable exhaustive switch-case handling.
enum NotificationType
BID_PLACED | AUCTION_WON | AUCTION_CLOSED | BID_REJECTED
Categorizes notification events to enable type-safe handling and filtering in notification dispatch.
enum BidStatus
ACCEPTED | REJECTED | WITHDRAWN
Tracks bid lifecycle status to manage bid validity and user feedback.
📦
Auction
8 fields
private final String auctionIdprivate volatile AuctionStatus statusprivate final double reservePriceprivate volatile Bid highestBidprivate final List<Bid> bidHistoryprivate final long startTimeMillisprivate final long endTimeMillisprivate final List<Bidder> registeredBidders
Manage auction lifecycle, accept bids atomically, enforce reserve price, track highest bid, and notify bidders on state changes.
public synchronized BidStatus placeBid(Bid bid)Atomically attempts to place a bid if auction is ACTIVE and bid amount exceeds current highest bid.
public synchronized void closeAuction()Closes auction, determines winner if reserve price met, and triggers notifications.
public synchronized void registerBidder(Bidder bidder)Registers a bidder to receive notifications and participate in bidding.
public synchronized Bid getHighestBid()Returns the current highest bid in a thread-safe manner.
public synchronized boolean isActive()Checks if auction status is ACTIVE.
📦
Bid
5 fields
private final String bidIdprivate final Bidder bidderprivate final double amountprivate final long timestampMillisprivate volatile BidStatus status
Represents a bid with immutable amount and bidder, tracks status changes.
public synchronized void withdraw()Marks bid as withdrawn if auction is still active.
public double getAmount()Returns bid amount.
public synchronized BidStatus getStatus()Returns current bid status.
📦
Bidder
3 fields
private final String bidderIdprivate final String nameprivate final String email
Represents a user who can place bids and receive notifications.
public void notify(Notification notification)Receives notifications asynchronously.
📦
Notification
3 fields
private final NotificationType typeprivate final String messageprivate final long timestampMillis
Encapsulates notification details sent to bidders.
public NotificationType getType()Returns notification type.
public String getMessage()Returns notification message.
📦
AuctionTimer
2 fields
private final Auction auctionprivate final ScheduledExecutorService scheduler
Manages auction timing, triggers auction close when timer expires.
public void start()Schedules auction close task at auction end time.
public void cancel()Cancels scheduled auction close if auction ends early.
📦
NotificationService
1 fields
private final ExecutorService notificationExecutor
Dispatches notifications asynchronously to bidders using thread pool.
public void sendNotification(Bidder bidder, Notification notification)Submits notification task to executor for asynchronous delivery.
🔗
Relationships
Auction◆──►Bid[1..*]
compositionBid lifecycle tied to Auction; bids do not exist independently
Auction◇──►Bidder[0..*]
aggregationBidder exists independently; Auction aggregates bidders for notification
AuctionTimer──►Auction[1]
associationAuctionTimer references Auction but does not own it
NotificationService──►Bidder[0..*]
associationNotificationService sends notifications to Bidder; no ownership
Bid──►Bidder[1]
associationBid references Bidder; Bidder exists independently
🗄️
Auctions
PK: auctionId
auctionId STRINGstatus STRINGreservePrice DOUBLEhighestBidId STRINGstartTimeMillis BIGINTendTimeMillis BIGINT
Stores auction metadata and status.
🗄️
Bids
PK: auctionId
bidId STRINGauctionId STRINGbidderId STRINGamount DOUBLEtimestampMillis BIGINTstatus STRING
Stores bids per auction ordered by timestamp.
🔌
POST
PlaceBid
Request
{
  "bidderId": "string",
  "amount": "double"
}
Response
{
  "bidStatus": "ACCEPTED|REJECTED|WITHDRAWN",
  "message": "string"
}
Places a bid on an active auction if amount is higher than current highest bid.
🔌
GET
GetAuctionStatus
Request
{}
Response
{
  "auctionId": "string",
  "status": "CREATED|ACTIVE|CLOSED",
  "highestBid": {
    "bidId": "string",
    "amount": "double",
    "bidderId": "string"
  },
  "reservePrice": "double",
  "startTimeMillis": "long",
  "endTimeMillis": "long"
}
Retrieves current auction status and highest bid.
🔌
POST
WithdrawBid
Request
{
  "bidderId": "string"
}
Response
{
  "success": "boolean",
  "message": "string"
}
Allows bidder to withdraw a bid before auction closes.

Practice

(1/5)
1. In designing an Elevator system using the State pattern, should the ElevatorState be an abstract class or an interface, and why?
easy
A. Interface, because states only define behavior without shared implementation
B. Abstract class, because states share common code and state variables
C. Abstract class, because it enforces a single inheritance hierarchy
D. Interface, because it allows multiple inheritance of state behaviors

Solution

  1. Step 1: Analyze shared code in states

    Elevator states often share common fields (e.g., reference to context) and helper methods, which favors an abstract class.
  2. Step 2: Evaluate interface limitations

    Interfaces cannot hold state or provide default implementations (prior to Java 8), so they are less suitable if shared code exists.
  3. Final Answer:

    Option B -> Option B
  4. Quick Check:

    Shared code and state -> abstract class [check]
Hint: Shared code and state -> abstract class; behavior only -> interface [check]
Common Mistakes:
2. A class has a private constructor and a static synchronized getInstance() method returning the single instance. Which pattern is applied and why is this the CORRECT use case?
easy
A. Singleton pattern, because it ensures only one instance exists and controls concurrent access.
B. Factory Method pattern, because it controls object creation with a static method.
C. Builder pattern, because it constructs complex objects step-by-step.
D. Prototype pattern, because it clones existing instances to avoid new construction.

Solution

  1. Step 1: Identify Singleton pattern characteristics

    The private constructor prevents external instantiation, and the static synchronized getInstance() method ensures a single instance with thread-safe lazy initialization.
  2. Step 2: Eliminate other creational patterns

    Factory Method controls subclass instantiation, Builder separates construction from representation, and Prototype clones objects; none enforce single instance or thread safety.
  3. Final Answer:

    Option A -> Option A
  4. Quick Check:

    Private constructor + synchronized static getInstance() -> Singleton pattern [check]
Hint: Private constructor + synchronized getInstance() -> Singleton [check]
Common Mistakes:
3. In the Workflow Engine, if the Executor class's executeStep() method is not synchronized, which exact thread interleaving causes two threads to execute the same step concurrently, leading to inconsistent state?
medium
A. Thread 1 finishes executeStep() before Thread 2 starts, so no concurrency issue occurs.
B. Thread 1 and Thread 2 both call executeStep() simultaneously and both complete without interference.
C. Thread 1 checks if step is not running -> true, context switch; Thread 2 checks same -> true; both proceed to execute concurrently.
D. Thread 1 locks the step, but Thread 2 waits indefinitely causing deadlock.

Solution

  1. Step 1: Identify the check-then-act race

    Without synchronization, Thread 1 checks step status as free, then context switches before marking running.
  2. Step 2: Thread 2 repeats check before Thread 1 marks running

    Thread 2 also sees step free and proceeds, causing both to execute concurrently.
  3. Final Answer:

    Option C -> Option C
  4. Quick Check:

    Unsynchronized check-then-act -> double execution race [check]
Hint: Check-then-act without sync -> race condition [check]
Common Mistakes:
4. In the Tic-Tac-Toe game server, the makeMove() method is not synchronized. Which exact sequence of events between Thread 1 and Thread 2 can cause two players to place their marks on the same cell (double-booking)?
medium
A. Thread 1 and Thread 2 both call makeMove() but on different board instances.
B. Thread 1 reads cell as empty, Thread 2 reads cell as occupied, both proceed to write.
C. Thread 1 locks the board, Thread 2 waits, then both mark different cells simultaneously.
D. Thread 1 checks cell is empty -> true, context switch before marking; Thread 2 checks cell is empty -> true, both mark cell concurrently.

Solution

  1. Step 1: Identify the race condition in makeMove()

    Without synchronization, the check-then-act sequence is vulnerable: Thread 1 checks if cell is empty and is preempted before marking.
  2. Step 2: Trace Thread 2's actions

    Thread 2 also checks the same cell, sees it empty, and proceeds to mark it. Both threads mark the same cell, causing double-booking.
  3. Final Answer:

    Option D -> Option D
  4. Quick Check:

    Check-then-act gap without sync -> double-booking race [check]
Hint: Check empty -> context switch -> both mark same cell [check]
Common Mistakes:
5. Adding a WeekendFeeStrategy to the parking lot pricing requires which minimum change to comply with SOLID principles?
medium
A. Modify the existing FeeCalculator class to add weekend logic with an if-else block.
B. Add a boolean isWeekend flag to Vehicle and change pricing logic accordingly.
C. Create a new WeekendFeeStrategy class implementing FeeStrategy and inject it without modifying existing classes.
D. Combine all fee strategies into one large class with multiple methods for each pricing rule.

Solution

  1. Step 1: Identify the SOLID principle involved

    The Open-Closed Principle (OCP) requires that classes be open for extension but closed for modification.
  2. Step 2: Evaluate options against OCP

    Create a new WeekendFeeStrategy class implementing FeeStrategy and inject it without modifying existing classes. respects OCP by adding a new strategy class without modifying existing code. Add a boolean isWeekend flag to Vehicle and change pricing logic accordingly. violates OCP by modifying Vehicle state, which is unrelated to pricing and causes tight coupling.
  3. Final Answer:

    Option B -> Option B
  4. Quick Check:

    New strategy class -> OCP-compliant extension [check]
Hint: OCP: add new class, don't modify existing ones [check]
Common Mistakes:
Recommended

Ready to prove it?

Pass the test and this pattern moves unknown strong while earning +1 Grip toward your certificate.

10 questions~5 mineasy hard