Appearance
9.7.1 — The LLD Interview: Method & Grading
"Design a parking lot." You have forty-five minutes, a shared editor, and an interviewer who will interrupt at minute thirty-five with a requirement you were not told about.
You are not being tested on whether you memorised the parking lot answer. You are being tested on whether you have a repeatable method you can run under time pressure on a problem you have never seen. This page is that method: nine steps, what each one produces, what gets graded, and the handful of moves that solve most of these problems. The pages after it work the classic machines (9.7.3 onwards).
1. The nine steps
The steps run roughly in order, and each one produces something the next one consumes. Skipping a step does not save time; it means you invent that step's output badly, later, under pressure.
Step 1 — Clarify the requirements
The prompt is deliberately vague. Turning it into a scoped problem is the first thing being graded, and candidates who start typing immediately have already lost points they will never learn about.
Ask about three things.
What is in scope today? "Park and unpark, plus payment on exit — is that the core, or should I include reservations?" Get an answer. An interviewer who says "keep it simple, park and unpark" has just handed you permission to skip an entire subsystem.
What varies? This is the highest-value category, and the one candidates skip. "Are there different vehicle sizes? Different pricing rules? More than one floor?" Every yes here becomes an interface later, and every no saves you from building one you did not need. When you hear "we might add motorbikes later", you have found where the twist is coming from.
What are the numbers? "How many spots? Is this one lot or a chain?" A hundred spots and a thousand spots are the same design. A hundred spots and ten million is not, and knowing which one you are in tells you whether an in-memory map is a reasonable answer or a joke.
Then say the sentence that converts an ambush into a contract:
"I am going to design for park, unpark and pay. I will make pricing and spot selection pluggable because you mentioned they vary. I am explicitly leaving out reservations and multi-lot for now — tell me if you would rather I include one of those."
Deferring something out loud is a senior signal. Silently not building it is a junior one. The words are what make the difference, and they cost you eight seconds.
Step 2 — List the actors
Who interacts with this system? For a parking lot: the driver, the gate attendant, an administrator who configures pricing. For a vending machine: the customer and the person who restocks it.
This takes thirty seconds and it earns its place because actors reveal flows you would otherwise forget. Nobody forgets that a driver parks. Plenty of people forget that an administrator has to be able to change the price, and that requirement is the one that forces pricing to be data rather than code.
Step 3 — Write the use cases
For each actor, list what they can do, as verb phrases. Driver: take a ticket, park, pay, exit. Attendant: see free spots, mark a spot broken. Administrator: set prices, add a floor.
These become your public methods. That is the whole reason for the step: a use case list is a first draft of your API, written in the language of the problem rather than the language of your data model. If a use case has no method by the end, you did not build the feature. If a method matches no use case, you built something nobody asked for.
Pick the one use case that is the heart of the system and say so: "parking a car is the flow I will implement end to end first." Everything else is negotiable when you run out of time; this one is not.
Step 4 — Find the entities
Go through your requirements and underline the nouns. Vehicle, spot, floor, ticket, payment, rate. Then sort each one into one of three boxes, because the box decides how you write it (9.2.1).
Entities have an identity that persists while their data changes. A Ticket issued at 9am is the same ticket at 5pm even though its exit time has been filled in. Entities get an id, and two of them are equal only if their ids match.
Value objects are defined entirely by their contents and never change after creation. Money, SpotSize, LicensePlate, TimeRange. Two Money objects holding £5 are interchangeable. Make them immutable and you never have to think about who else is holding a reference.
Roles are the things that vary, from step 1. PricingStrategy, SpotAllocator. These become interfaces.
The one rule that matters here: Money is always a type, never a number. Floating point money is wrong (1.4), and an interviewer who sees price: number will ask you about 0.1 + 0.2 and enjoy it. Integer minor units inside a Money value object, every time.
Step 5 — Draw the relationships
For each pair of classes that know about each other, say which kind of relationship it is and what the numbers are. A lot has floors. A floor has spots. A ticket references one vehicle and one spot.
The distinction that earns marks is ownership. A floor cannot exist without its lot, and deleting the lot deletes the floors — that is composition. A ticket references a vehicle, but the vehicle exists perfectly well without the ticket — that is association. 9.7.2 covers the notation; the reason to be careful here is that ownership decides who is allowed to create and destroy what, and getting it wrong produces objects that outlive their parents and rows that cannot be deleted.
Say the cardinalities out loud: "one ticket, one spot, one vehicle; one floor, many spots." The moment you say "one ticket can cover many spots" you have discovered a requirement nobody mentioned, and asking about it right then is worth more than any code you could write in the same minute.
Step 6 — Write the interfaces first
Before any implementation, write the method signatures. The interfaces are the design; the implementations are typing.
typescript
interface PricingStrategy {
quote(entry: Instant, exit: Instant, size: SpotSize): Money; // (1)
}
interface SpotAllocator {
allocate(size: SpotSize, lot: LotView): Spot | null; // (2)
}
class ParkingLot {
park(vehicle: Vehicle, at: Instant): Ticket; // (3)
unpark(ticketId: TicketId, at: Instant): Receipt;
}(1) The pricing rule takes everything it could need and returns Money. Note that it takes an exit time rather than reading a clock, which makes it a pure function you can reason about — and it means a "what would this cost at midnight" feature needs no clock manipulation at all.
(2) Allocation returns null for a full lot rather than throwing, because a full lot is an ordinary Tuesday, not an exceptional event. Reserve exceptions for things that should not happen.
(3) The lot's own API is exactly the driver's use cases from step 3, which is the check that steps 3 and 6 agree with each other.
Two or three interfaces is the right number for a forty-five minute problem. One means the twist will force a rewrite. Seven means you are abstracting things that never varied, which reads as inexperience rather than sophistication (9.3.4).
Step 7 — Write the core flow, end to end
One complete path that runs beats five stubs that do not. Implement the use case you named in step 3, all the way through, and prioritise the code that shows design judgement over the code that is just plumbing.
The code worth your minutes is: the state machine's transition function, the strategy registry, and any method that guards an invariant. The code not worth your minutes is getters, constructors that only assign fields, and a toString. If you are short on time, write the signature and say "the body here is straightforward assignment, let me spend the time on the allocation logic instead". Interviewers respect that; they are watching the clock too.
Narrate as you type. "I am using a Map from ticket id to ticket because unpark is a lookup by id — if we also needed unpark-by-plate I would add a second index."
Step 8 — Name the concurrency
At some point two users will want the same thing. In a parking lot it is the last free spot. In a booking system it is the last seat. In a wallet it is the balance.
Say it before you are asked. "Two cars can reach the last spot at the same moment, so the claim has to be atomic — I will make spot.claim() a conditional operation that fails if the spot is already taken, and the caller retries with the next candidate."
Nobody expects a distributed lock in minute forty. Everybody expects you to see the race and to put the guard on the state rather than in the handler (9.5.1). One guarded method and one sentence about what happens when it loses is a full pass on this axis.
Step 9 — Handle the twist
The interviewer will change a requirement. "Now add electric vehicle charging spots." "Now pricing is higher at weekends." "Now there are two lots."
If step 1 found the right variation axes, the twist lands as a new class and one line in a registry. Walk it out loud: "WeekendPricing implements PricingStrategy, I register it here, and no existing file changes." That is the Open/Closed Principle paying out on schedule (9.3.6), and the interviewer is watching for exactly this sentence.
If it does not land cleanly, say so. "This one does not plug in — EV spots need a charger relationship that my Spot does not have, so I would add it as a capability set on Spot and change the allocator's filter. Two files, and here is why I did not anticipate it." Visible re-planning beats silent hacking every time, because the interviewer already knows it does not fit.
2. What is actually being graded
Five axes. Knowing them lets you play to the test, which is not cheating — it is understanding the job you are interviewing for.
| Axis | Passing looks like | Failing looks like |
|---|---|---|
| Requirements | Scoped and deferred out loud | Started coding at minute two |
| Modelling | Rules live inside entities | Rules float in a service |
| Extensibility | Two or three interfaces, each justified | Everything hard-coded, or everything abstract |
| Code | One flow runs; the race is named | Five stubs; no concurrency mentioned |
| Communication | Every choice gets its reason said | Silence, then a finished design |
The second row deserves expanding because it is where most otherwise-good candidates lose points. A ParkingLot that exposes its spots array so the caller can set spot.occupied = true has put the rule in the wrong place. Every caller must now remember to check occupancy first, and one of them eventually will not. The fix is one line of design: spot.assign(vehicle) checks its own occupancy and throws if it is already taken (9.2.2). The object that owns the data owns the rule about the data.
The third row is worth a warning in the other direction. An AbstractVehicleFactoryProvider in a parking lot is not a sophistication signal; it is a signal that you apply patterns without asking whether the variation exists. Interfaces belong on axes the requirements actually demonstrated.
3. The six moves that solve most of these problems
These are not new theory. They are Part 9's patterns applied, and if you can recognise which ones a problem needs, the skeleton assembles itself.
A state machine for anything with a lifecycle. An elevator is idle, moving up, moving down, or has its doors open. A vending machine is waiting for money, has money, or is dispensing. An order is placed, paid, packed, shipped. List the states, write one transition function, reject illegal moves loudly (9.4.14). Half the correctness questions an interviewer might ask are pre-answered by an exhaustive transition function.
A strategy plus a registry on every axis that varies. Pricing, allocation, eviction, routing, how a bill gets split. A Record<Kind, Strategy> gives you a table where a missing entry is a compile error rather than a runtime surprise (9.4.12). The twist almost always lands here, which is why step 1 spends its time hunting for these.
Entities guard their invariants; values are immutable. spot.assign(vehicle) checks occupancy. wallet.debit(amount) checks the balance. Money never changes. This single habit is the difference between a design that stays correct as it grows and one that needs every caller to be careful.
Composite for anything shaped like a part inside a whole. Lot, floor, spot. Board, square. Folder, file. It gives you uniform traversal and makes "count the free spots on floor 2" and "count the free spots in the lot" the same method (9.4.11).
A conditional claim wherever two users can want the same thing. Step 8's move, and the single most reliable way to look experienced.
Observer for the things around the edges. Display boards, notifications, logging, analytics. These subscribe to events and are never on the path that must succeed (9.4.13). Saying "the display board is a subscriber, so if it fails nobody's car is stuck" shows you can tell essential from decorative.
4. Classify first, then the skeleton writes itself
The prompts rotate because memorised answers are worthless. What transfers is the observation that most of these problems are the same four problems.
| Class | Prompts | What the skeleton always has |
|---|---|---|
| Allocation | Parking, hotel, seats, meeting rooms | Bounded resources, a claim, a release, a pricing rule |
| Lifecycle | Elevator, order, traffic signal, ATM | States, transitions, a scheduling policy |
| Bounded resource | Rate limiter, cache, connection pool | A limit, a refill or eviction rule, a decision function |
| Rules engine | Chess, snakes and ladders, tic-tac-toe | A board, legal-move generation, a win condition |
When an unseen prompt arrives, classify it aloud in the first minute. "This is an allocation problem with a booking window, so it is the parking lot with a time dimension — bounded resources, a claim that can race, and a pricing rule that varies." You have just told the interviewer you have a method, and you have given yourself a skeleton to fill.
5. Time discipline is part of the design skill
The most common failure is not a bad design. It is minute thirty with a beautiful class diagram and no code, or minute twenty deep inside an edge case about pricing rounding while the core flow is unwritten.
Rough budget for forty-five minutes: eight on requirements, ten on entities and relationships, seventeen on interfaces and the core flow, ten for the twist and questions. When requirements threaten to run long, park the open questions visibly — "I am noting reservations and multi-lot as open, moving on" — and move. Asking permission to defer is free.
Breadth before depth. Get the whole flow working shallowly, then deepen wherever the interviewer's questions steer you. A complete shallow design can be deepened in conversation. A deep fragment cannot be completed in five minutes.
6. Say the quiet part
Two candidates produce the same final design. One passes. The difference is that one of them narrated: why a Map rather than an array, where the race is, what breaks at a hundred times the scale, which requirement would force a restructure rather than an extension.
An LLD interview is a design review being simulated, and you are hosting it. Silence reads as luck. Narration reads as judgement, and judgement is the thing being bought.
Next: 9.7.2 covers the four diagrams worth drawing in an interview, what each one is for, and how to draw them fast enough to be useful.
Recall
- Nine steps: clarify scope and what varies → actors → use cases (they become your methods) → entities, values and roles → relationships with cardinalities → interfaces first → the core flow end to end → name the race → absorb the twist.
- Say the contract out loud at minute eight: what is in, what is pluggable, what you are deferring. Silent deferral reads as forgetting.
- Money is a type, never a number. Integer minor units inside a value object.
- Graded: requirement handling · invariants inside entities, not in a service · interfaces only on demonstrated axes · one flow that runs plus the race named · constant narration.
- Six moves: state machine for lifecycles · strategy plus registry per varying axis · entities guard, values immutable · Composite for part-and-whole · conditional claim at the contested resource · Observer for the periphery only.
- Four classes of problem: allocation · lifecycle · bounded resource · rules engine. Classify first and the skeleton follows.
- Budget 8 / 10 / 17 / 10. The two standard failures are a beautiful diagram with no code, and an edge case rabbit hole with the core flow unwritten.
Self-test: What three things do you ask about in step 1, and which one is most valuable? Why do use cases come before entities? Where should the rule "a spot cannot be assigned twice" live, and why? Where does the twist usually land? Classify a hotel booking system, a traffic signal, and a connection pool.
Quiz Bank
FoundationalWalk the LLD method step by step, and say what each step produces that the next step needs.
Clarify requirements produces a scoped problem. Three questions: what is in scope, what varies, and what the numbers are. The middle one is the most valuable, because every "yes, that varies" becomes an interface and every "no" saves you from building one. Close it by stating the contract out loud, including what you are deliberately not building.
Actors produces a list of who uses the system, and its value is that it surfaces flows you would otherwise forget — the administrator who has to change prices is the reason pricing ends up as data rather than as code.
Use cases produces a first draft of the public API, written in the problem's language rather than the data model's. Every use case should end up as a method; every method should trace back to a use case.
Entities produces the classes, sorted into three kinds: entities with identity, immutable value objects, and roles that vary. The sorting is what decides how each one is written — ids and equality for entities, immutability for values, interfaces for roles.
Relationships produces the ownership and the cardinalities. Ownership decides who creates and destroys what. Saying the numbers out loud is how you discover unstated requirements, because "one ticket covers one spot" is a claim somebody may want to contradict.
Interfaces produces the design itself. Everything after this is typing. Two or three interfaces is right for a short problem.
The core flow produces evidence that it works. One complete path, prioritising code that shows judgement over code that assigns fields.
Naming the concurrency produces the senior signal, and it must be volunteered rather than extracted.
The twist produces the proof the design was right. If the axes were correct it is a new class and a registry line, and you should walk exactly which files change and which do not.
The dependency chain is the point. Requirements name the variation, variation becomes interfaces, interfaces are the design, and the twist tests whether you put them in the right places. Skip the first step and everything after it is guesswork with good syntax.
AppliedYou get an unseen prompt: design a library seat-booking system. Produce the skeleton in two minutes of talking, using the method.
Classify first. This is allocation with a time dimension — the parking lot plus a booking window, which makes it the hotel-reservation shape. Say that out loud; it tells the interviewer you have a method and it gives you a skeleton to fill.
Scope and variation. In scope: browse free seats, book one for a slot, check in, release. Deferred out loud: payments, recurring bookings, waiting lists. What varies, and this is where the interfaces come from: how a seat is chosen (nearest window, quiet zone, accessible) and what the booking rules are (maximum hours, different limits per membership tier).
Actors and use cases. Member: search, book, check in, cancel. Librarian: mark a seat out of service, see occupancy. Administrator: set the booking rules. That last actor is why the rules are a strategy rather than a constant.
Entities, values, roles. Entities: Seat, which guards its own occupancy, and Booking, which has a lifecycle, and Member. Values: TimeSlot, SeatFeatures. Roles: SeatAllocator and BookingPolicy.
Relationships. Library → Zone → Seat as a Composite, which makes "how many free seats in the quiet zone" and "how many free seats in the library" the same call. One booking references one seat and one member, and stating that invites the question of whether a group booking exists — which is worth asking now rather than discovering at minute forty.
The lifecycle. Booking: reserved → checked_in → completed | expired | cancelled, with one transition function. Expiry is worth a sentence: it should be implicit in the data — a booking whose slot has passed and which was never checked into is expired by definition — rather than a background job that writes a status, because a job that writes races with a member checking in at that exact moment (9.5.1).
The race, volunteered. Two members booking the last quiet seat. The claim is a conditional operation on the seat: take it only if it is still free for that slot, and treat losing as an ordinary outcome that shows "someone just took that one" rather than as an error.
The periphery. Occupancy display boards and reminder notifications subscribe to booking events, and none of them are on the path that must succeed.
And the sentence that banks a bonus point: "if you want waiting lists, that is one owner per contested seat processing a queue of requests in order, which I would add as a per-seat queue rather than a global lock." Two minutes, every move from the toolkit, and not one line of it memorised.
InterviewTwo candidates produce the same final class diagram. One passes and one does not. What did the passing candidate do?
Five observable behaviours, none of which show up in the diagram.
They authored the scope rather than discovering it. The passing candidate said at minute eight what was in, what was pluggable, and what was deferred. The other candidate found the boundaries by being interrupted, which reads as being led rather than leading.
They put the rules inside the objects that own the data. spot.assign(vehicle) checks occupancy itself. The other candidate's checks live in a service method, which means every future caller has to remember them, and the diagram looks identical because a diagram does not show where the if statements are. This is the anemic model tell (9.2.2), and it is visible in twenty lines of code.
They abstracted exactly the axes the requirements demonstrated. Two or three interfaces, each with a stated reason. The failing candidate either hard-coded everything, so the twist required a rewrite, or abstracted everything, which is the speculative-generality signal (9.3.4). Again the diagram may look the same; the difference is whether each interface had a reason or a habit behind it.
They saw the race without being asked. "Two cars reach the last spot at the same moment, so the claim is conditional and the loser retries." Said unprompted, that is a senior signal. Bolted on when probed, it is a correct answer to a question somebody else raised.
They priced every structure out loud. Why a Map and not an array. What breaks at a hundred times the scale. Which requirement would force a restructure rather than an extension. The interview is a design review, and the candidate who narrates is behaving like the person who will host those reviews on the team. That is the trait being purchased, and it is the whole reason two identical designs get different outcomes.
StaffYou are designing your company's LLD interview loop. Define the problem bank, the rubric and the calibration, and justify each choice.
The problem bank: six to eight prompts covering the four classes. Allocation, lifecycle, bounded resource, rules engine. Covering all four matters because a bank made only of allocation problems selects for candidates who have seen parking lots, not for candidates with a method.
Each prompt needs a written clarification script — the same answers to the same likely questions, for every candidate. This is the loop's biggest fairness hole and almost nobody closes it: an unscripted interviewer gives one candidate "assume a single floor" and another "there are twelve floors and three vehicle types", and then the scores get compared as if they measured the same thing.
Each prompt also needs two prepared twists of graded difficulty: one that should plug into a well-chosen interface, and one that genuinely requires restructuring. The second one is not a trap. It tests whether a candidate can say "this does not plug in, here is what I would change and why I did not anticipate it", which is a more useful behaviour than never being surprised.
Rotate the bank quarterly and retire leaked prompts. But note the nuance: a candidate who recognises the problem class and adapts is still showing the skill you want. One who recites spot-type enums from a blog post is not, and the twist is exactly what separates them. That is why twists are mandatory rather than optional.
The rubric: the five axes, with anchored descriptors. An anchor is a concrete observable behaviour at each score, not an adjective. "Modelling, 4: invariants placed inside entities without prompting." "Modelling, 2: checks written in the service layer, moved into the entity when the interviewer probes." Anchors are the only thing that makes two interviewers' scores mean the same thing, and a rubric without them is a mood ring.
Grade the code axis on core-flow completeness and design-bearing code, explicitly not on syntax recall or lines produced. State this in the guide, because otherwise interviewers unconsciously reward fast typists.
Calibration mechanics. New interviewers shadow three sessions and reverse-shadow two, with a score-comparison debrief each time. Quarterly, the whole panel re-grades two recorded or transcribed sessions against the anchors and discusses the disagreements — the disagreements are the point, not the average. Monitor per-interviewer score distributions for drift, because every panel has someone scoring a full point above everyone else and nobody notices without the data.
Protect the time protocol. Fix it at roughly eight, ten, seventeen and ten, and make it the interviewer's job to move the candidate along. An interviewer who lets requirements run for twenty minutes has destroyed the code signal and will then score the candidate down for not producing code, which is unfair and also uninformative.
State the anti-goals in the guide. No trick constraints. No framework trivia. No concurrency gotchas beyond naming the race and guarding one method. The loop is measuring the method, because the method is what transfers to the job — and because the four problem classes mean a candidate with a method handles prompts the bank does not contain yet, which is precisely the trait you are trying to buy.
Flashcards
FlashThe nine steps
Scope and what varies · actors · use cases · entities, values, roles · relationships with cardinalities · interfaces first · core flow end to end · name the race · absorb the twist.
FlashFive graded axes
Requirement handling · invariants inside entities · interfaces only on demonstrated axes · a flow that runs plus a named race · continuous narration.
FlashThe six moves
State machine for lifecycles · strategy plus registry per varying axis · entities guard and values are immutable · Composite for part-and-whole · conditional claim at the contested resource · Observer for the periphery.
FlashFour problem classes
Allocation (parking, hotel, seats) · lifecycle (elevator, orders, signals) · bounded resource (limiter, cache, pool) · rules engine (chess, tic-tac-toe). Classify before designing.
FlashThe two standard failures
Minute thirty with a beautiful diagram and no code. Minute twenty inside a rounding edge case with the core flow unwritten. Budget 8 / 10 / 17 / 10.
Scenario Drill
DrillRun the full method on an unseen prompt: a food court where customers order at stalls, receive a buzzer, get paged when food is ready, and return the buzzer on pickup. Buzzers are a limited pool and stalls differ in how they prepare food. Perform it phase by phase as you would live.
Minutes 0–8, scope and variation. Actors: customer, stall operator, and an administrator who manages buzzer inventory. In scope: issue a buzzer when an order is placed, page when the food is ready, take the buzzer back at pickup. Deferred out loud: payments, one buzzer covering orders from two stalls, buzzer battery management.
Two variation axes found, and naming them is the whole value of this phase. How a stall decides food is ready differs — a made-to-order stall marks one order ready at a time, a biryani stall marks fifteen ready at once when a batch comes out. And how paging escalates differs — page once, or page repeatedly until collected. Both become interfaces.
Classification said aloud: this is a bounded resource pool (the buzzers) wrapped around a per-order lifecycle. So it is the connection pool problem and the order problem at the same time, and I already know the shape of both.
Minutes 8–18, the model. Entities: Buzzer, which guards its own state of available, assigned, paging or returned; Order, which has the lifecycle; Stall. Values: TokenNumber, PrepEstimate. Roles: ReadinessPolicy per stall, and PagingPolicy.
The pool is the worker-pool shape from 9.5.4, holding Buzzer entities with claim and release, bounded, and waiters queued when empty. Cardinality stated deliberately: one active order per buzzer — and naming it flags the deferred multi-stall feature as the exact joint that requirement would hit.
Minutes 18–35, the code that shows design. Three things get written, in this order.
The Order state machine: placed → preparing → ready → picked_up | abandoned, as one exhaustive transition function. Abandonment is a timeout evaluated against the stored state rather than a background job that writes, and the buzzer is released as part of that transition rather than by a separate sweeper — which keeps the two facts, "order abandoned" and "buzzer free", from ever disagreeing.
BuzzerPool.claim(), with the empty-pool policy asked rather than assumed: "when we run out of buzzers, should the cashier be blocked, or should we fall back to SMS paging? I will code the SMS fallback as another PagingChannel." That is a resource limit being absorbed by an interface that already exists, and narrating it is worth more than the code.
Buzzer.assign(order), which refuses to assign a buzzer that is already assigned. The rule lives with the data.
The display board and the operations dashboard subscribe to transitions, and neither is on the path that must succeed.
Minutes 35–45, the twists, pre-walked. "Support customers who want SMS instead of a buzzer" — the PagingChannel interface already exists, so this is a new class, one registry line, and BuzzerPool is untouched. "Buzzers are now shared between two food courts" — the pool partitions by court, and I would say which invariant moves rather than pretending nothing changes. "One buzzer covers orders from two stalls" — this is the deferred joint I named at minute five, and it genuinely restructures: the cardinality flips to one buzzer with many orders, and readiness becomes an aggregation rule (page when all are ready, or page for each). Admitting that this one restructures rather than plugs is exactly the narration that scores, because the alternative is pretending a design absorbs everything, which no design does.
What made the performance work: every phase produced its output on time, every structure had its cost said out loud, and both kinds of twist — the one that plugs in and the one that does not — were handled by name.