LLD & Machine Coding Cheatsheet — Stripe / FAANG
1. Machine Coding — How to Approach (45–60 min)
Step-by-step framework What Stripe looks for
• 1. Clarify requirements (5 min) — ask, don't assume • Clean class separation — single responsibility
• 2. Identify entities / classes (3 min) • Interfaces/abstractions over concrete classes
• 3. Define interfaces & relationships (5 min) • Extensible — easy to add new rules/types
• 4. Code core logic first, then extend (30 min) • Edge cases handled (null, empty, duplicates)
• 5. Handle edge cases + write test cases (7 min) • Self-testing — write main() with test cases
Questions to ask upfront Class design checklist
• What are the actors? (user, admin, system?) • Every class has ONE clear responsibility
• What operations are needed? (CRUD, search, filter?) • Use interfaces where behaviour varies
• Any concurrency? (thread safety needed?) • Enums for fixed sets (Status, Type, Role)
• Scale? (in-memory ok, or persistence needed?) • No God classes — split if > 3 responsibilities
• Any notifications / events / callbacks? • Collections private — expose via methods only
2. SOLID Principles — Quick Reference
Principle Rule Example
S Single Responsibility One class = one reason to change PaymentProcessor should NOT also send emails
O Open/Closed Open for extension, closed for modification Add new PaymentMethod by implementing interface, not editing
existing class
L Liskov Substitution Subclass must be usable in place of parent CreditCard extends PaymentMethod — all PaymentMethod methods
must still work
I Interface Segregation Don't force classes to implement unused Split FraudChecker from TransactionLogger — separate
methods interfaces
D Dependency Inversion Depend on abstractions, not concretions PaymentService depends on IPaymentGateway, not StripeGateway
directly
3. Design Patterns — Most Asked in LLD
Creational Behavioural
// Singleton — one instance only // Observer — event notification
class Config { interface Observer { void update(Event e); }
private static Config instance; class EventBus {
private Config() {} Map<String,List<Observer>> listeners = new HashMap<>();
public static synchronized Config get() { void subscribe(String ev, Observer o) {
if (instance == null) instance = new Config(); [Link](ev, k->new ArrayList<>()).add(o);
return instance; }
} void publish(String ev, Event e) {
} [Link](ev, [Link]()).forEach(o->[Link](e));
}
// Factory — hide creation logic }
interface Payment { void pay(); }
class PaymentFactory { // Strategy — swap algorithms at runtime
static Payment create(String type) { interface FraudStrategy { boolean isFraud(Txn t); }
return switch(type) { class RuleBasedFraud implements FraudStrategy { ... }
case "card" -> new CardPayment(); class MLBasedFraud implements FraudStrategy { ... }
case "upi" -> new UpiPayment(); class FraudDetector {
default -> throw new IllegalArgumentException(); private FraudStrategy strategy;
}; FraudDetector(FraudStrategy s) { strategy = s; }
} boolean check(Txn t) { return [Link](t); }
} }
// Builder — complex object construction // Decorator — add behaviour without subclassing
class Order { interface Logger { void log(String msg); }
private Order(Builder b) { ... } class ConsoleLogger implements Logger {
static class Builder { public void log(String m) { [Link](m); }
private String item; private int qty; }
Builder item(String i){ item=i; return this; } class TimestampLogger implements Logger {
Builder qty(int q) { qty=q; return this; } Logger wrapped;
Order build() { return new Order(this); } TimestampLogger(Logger l) { wrapped = l; }
} public void log(String m) {
} [Link]([Link]() + " " + m);
// Usage: new [Link]().item("x").qty(2).build(); }
}
Structural Concurrency / State
// Adapter — make incompatible interfaces work // State — object changes behaviour by state
interface NewPaymentAPI { void charge(double amt); } interface OrderState { void next(Order o); }
class OldGateway { void processPayment(int cents) {...} } class PendingState implements OrderState {
class GatewayAdapter implements NewPaymentAPI { public void next(Order o) { [Link](new PaidState()); }
OldGateway legacy; }
public void charge(double amt) { class PaidState implements OrderState {
[Link]((int)(amt * 100)); public void next(Order o) { [Link](new ShippedState()); }
} }
} class Order {
private OrderState state = new PendingState();
void setState(OrderState s) { state = s; }
void advance() { [Link](this); }
}
LLD & Machine Coding Cheatsheet — Page 2
4. Parking Lot — Most Common LLD Question
Entities Core Logic + Ticket
enum VehicleType { BIKE, CAR, TRUCK } class Ticket {
enum SpotType { SMALL, MEDIUM, LARGE } String id;
enum SpotStatus { FREE, OCCUPIED } Vehicle vehicle;
class Vehicle { ParkingSpot spot;
String plate; LocalDateTime entryTime;
VehicleType type; }
} class ParkingLot {
class ParkingSpot { List<ParkingSpot> spots;
int id; SpotType type; Map<String,Ticket> active; // plateNo -> Ticket
SpotStatus status; Ticket park(Vehicle v) {
Vehicle parkedVehicle; SpotType needed = getSpotType([Link]);
boolean isAvailable() { ParkingSpot spot = [Link]()
return status == [Link]; .filter(s->[Link]==needed && [Link]())
} .findFirst().orElseThrow();
void park(Vehicle v) { [Link](v);
parkedVehicle = v; Ticket t = new Ticket(v, spot, [Link]());
status = [Link]; [Link]([Link], t);
} return t;
void vacate() { }
parkedVehicle = null; double exit(String plate) {
status = [Link]; Ticket t = [Link](plate);
} [Link]();
} return calculateFee(t);
}
SpotType getSpotType(VehicleType vt) {
return switch(vt) {
case BIKE -> [Link];
case CAR -> [Link];
case TRUCK -> [Link];
};
}
}
5. Rate Limiter — Classic Stripe Question
Sliding Window (most asked) Token Bucket variant
class RateLimiter { class TokenBucket {
int maxRequests; double capacity;
long windowMs; double tokens;
// userId -> queue of timestamps double refillRate; // tokens per ms
Map<String,Deque<Long>> windows = new HashMap<>(); long lastRefill;
RateLimiter(int max, long windowMs) { TokenBucket(double cap, double ratePerSec) {
[Link] = max; capacity = cap;
[Link] = windowMs; tokens = cap;
} refillRate = ratePerSec / 1000.0;
synchronized boolean allow(String userId) { lastRefill = [Link]();
long now = [Link](); }
Deque<Long> q = [Link]( synchronized boolean consume(double n) {
userId, k -> new ArrayDeque<>()); refill();
// evict old timestamps if (tokens >= n) { tokens -= n; return true; }
while (![Link]() && now - [Link]() > windowMs) return false;
[Link](); }
if ([Link]() < maxRequests) { private void refill() {
[Link](now); long now = [Link]();
return true; // ALLOWED tokens = [Link](capacity,
} tokens + (now - lastRefill) * refillRate);
return false; // BLOCKED lastRefill = now;
} }
} }
Per-tier limits (Stripe follow-up)
enum Tier { FREE, PREMIUM, ENTERPRISE }
Map<Tier, Integer> limits = [Link](
[Link], 5,
[Link], 100,
[Link], 10000
);
boolean allow(String userId, Tier tier) {
int max = [Link](tier);
// use same sliding window, pass max
}
6. LRU Cache — Frequently Asked
Node + DoublyLinkedList Get / Put operations
class Node { int get(int key) {
int key, val; if () return -1;
Node prev, next; Node n = [Link](key);
Node(int k, int v) { key=k; val=v; } remove(n); addToFront(n);
} return [Link];
class LRUCache { }
int capacity; void put(int key, int val) {
Map<Integer,Node> map = new HashMap<>(); if ([Link](key)) remove([Link](key));
Node head = new Node(0,0); // dummy Node n = new Node(key, val);
Node tail = new Node(0,0); // dummy addToFront(n); [Link](key, n);
LRUCache(int cap) { if ([Link]() > capacity) {
capacity = cap; Node lru = [Link];
[Link] = tail; remove(lru); [Link]([Link]);
[Link] = head; }
} }
void remove(Node n) {
[Link] = [Link];
[Link] = [Link];
}
void addToFront(Node n) {
[Link] = [Link]; [Link] = head;
[Link] = n; [Link] = n;
}
}
7. Reusable LLD Patterns — Keep Handy
Enum for state machine Thread-safe Singleton
enum OrderStatus { class DatabasePool {
PENDING, CONFIRMED, SHIPPED, // Double-checked locking
DELIVERED, CANCELLED; private static volatile DatabasePool instance;
boolean canTransitionTo(OrderStatus next) { private DatabasePool() {}
return switch(this) { public static DatabasePool getInstance() {
case PENDING -> next==CONFIRMED || next==CANCELLED; if (instance == null) {
case CONFIRMED -> next==SHIPPED || next==CANCELLED; synchronized ([Link]) {
case SHIPPED -> next==DELIVERED; if (instance == null)
default -> false; instance = new DatabasePool();
}; }
} }
} return instance;
}
Generic Event Bus }
class EventBus {
Idempotency Key (Stripe-specific)
private static EventBus INSTANCE;
Map<Class<?>, List<Consumer<Object>>> handlers = new HashMap<>();class IdempotencyStore {
public <T> void subscribe(Class<T> type, Consumer<T> h) { Map<String, Response> store = new ConcurrentHashMap<>();
[Link](type, k->new ArrayList<>()) Response processOrGet(String key,
.add(e -> [Link]([Link](e))); Supplier<Response> action) {
} return [Link](key,
public void publish(Object event) { k -> [Link]());
[Link]([Link](), [Link]()) }
.forEach(h -> [Link](event)); }
} // Same idempotency key -> returns cached response
} // Different key -> executes action
8. Common Machine Coding Problems & Key Classes
Problem Key Classes Key Pattern Edge Cases
Parking Lot Vehicle, ParkingSpot, Ticket, ParkingLot Factory for spot allocation Full lot, multiple floors, EV spots
Rate Limiter RateLimiter, TokenBucket, UserTier Sliding window / Token bucket Concurrent requests, tier limits
LRU Cache Node, LRUCache DoublyLinkedList + HashMap Capacity=1, duplicate keys
Elevator System Elevator, Request, Scheduler Strategy for scheduling Multiple elevators, emergency
Library Mgmt Book, Member, Loan, Catalog Observer for due dates Overdue fines, reservations
Hotel Booking Room, Booking, Guest, Invoice State machine for booking Overlap check, cancellation
ATM Machine Card, Account, Session, Cash State machine (idle/auth/txn) Wrong PIN, insufficient cash
Snake & Ladder Board, Player, Dice, Snake, Ladder Command pattern for moves Multiple snakes same cell
Chess Board, Piece, Move, Player Strategy per piece type Check/checkmate detection
Splitwise User, Group, Expense, Balance Graph for debt settlement Circular debts, simplify
Ride Sharing Rider, Driver, Trip, Location Observer + Strategy Driver availability, surge
Movie Booking Movie, Screen, Seat, Booking State for seat (free/locked/booked) Race condition on seat booking
9. Interview Tips — Do's & Don'ts
Do's Don'ts
• Start with clarifying questions — never assume • Don't write a God class with 10+ methods
• Name classes/methods after business concepts, not tech • Don't use String for statuses — use enums
• Write an interface first, implement second • Don't ignore concurrency if asked for a service
• Use enums for status, types, roles • Don't hardcode — use constants or config
• Always write main() with 2-3 test cases • Don't start coding before finishing design
• Talk through trade-offs (thread-safe vs performance) • Don't forget edge cases (null, empty, max capacity)
• Model the real world — use nouns as class names • Don't over-engineer with patterns you don't need
• Keep collections private, expose via getter methods • Don't use public fields — always private + methods
LLD & Machine Coding Cheatsheet • Stripe / FAANG Interviews • Good luck! ■