Free preview

Why this matters: a logging framework sounds like the easiest problem in the machine-coding canon — everyone has used one. That familiarity is the trap: candidates design the library they remember instead of the one being asked for, and skip the requirements conversation entirely. But this prompt hides one of the best scoping questions in the whole problem set, and interviewers are listening for whether you find it.

The prompt, as given

Design a logging library for backend services.

Every service in the company will embed it: application code asks for a logger, writes messages at some severity, and those messages end up wherever the operators need them — possibly more than one place, possibly formatted differently per place. Messages carry structured data, not just prose.

Read it twice and notice the load-bearing phrases: more than one place, formatted differently per place, structured data. Each is a requirements thread waiting to be pulled.

The questions, and why each one matters

"What are the levels — and where does level filtering live?" The first half is easy (DEBUG < INFO < WARN < ERROR, almost always). The second half is the question that separates candidates: does a minimum level belong to the logger, to the destination, or both? A real answer — each named logger has a minimum, and each destination may impose its own stricter one, so the console can sit at INFO while the file collects DEBUG — means your design needs two filtering gates in different layers. Candidates who never ask design one gate and discover the second as a bug.

"What destinations, and how many at once?" Console, a rolling file, an HTTP shipper to a collection endpoint — and yes, several active simultaneously for the same message. "Several at once" is the requirement that forces a real dispatch layer; "formatted differently per place" is the one that forces formatting and writing apart.

"What does 'structured data' mean exactly?" Key-value fields attached to an individual message is table stakes. The sharper follow-up: can fields be bound to a logger, so a request-scoped logger stamps request_id on everything it emits without every call site repeating it? That answer creates one of the design's best objects — and one of its subtlest bugs, which lesson 02 names.

"What may logging cost the caller?" The professional's question. A suppressed DEBUG message — one filtered out by level — must cost almost nothing on the hot path, because services run with DEBUG call sites compiled in everywhere. This single requirement will dictate the order of operations inside your log call.

"Who calls this, from how many threads?" Many threads, concurrently; the library must be safe. And the ordering follow-up: one thread's messages should appear in order at any given destination — no promises across threads. Asking about ordering marks you as someone who has debugged interleaved logs at 3 a.m.

"How is it configured?" Named loggers (payments.checkout), configuration resolved at startup, no runtime reload. Startup-only configuration is a genuine simplification — you get to say why later.

The requirement set this chapter builds against

Levels         DEBUG < INFO < WARN < ERROR
Filtering      TWO places: per-logger minimum, plus an optional
               stricter per-destination minimum
Destinations   console, rolling file, HTTP shipper — several at once
Fields         key-value pairs per message AND bindable to a logger
Loggers        named ("payments.checkout"); config resolved at startup
Cost           a suppressed DEBUG must cost ~nothing on the hot path
Writes         synchronous, on the calling thread
Threading      many concurrent callers; per-thread ordering holds
               at any one destination; no cross-thread promises
Out of scope   runtime config reload, log rotation mechanics

The design already visible in the table: two gates in two layers; formatting split from writing (different formats per destination); a message as a value that several destinations can consume; and a hot-path rule that will put the level check before everything else.

As always: a live interviewer's answers may differ — maybe their levels include TRACE, maybe fields are message-only. The conversation is the skill; this particular answer sheet is just the one we build against.

Key takeaway

The logging prompt rewards the scoping questions everyone skips: where filtering lives (two gates, two layers), whether several destinations consume one message (a real dispatch layer), whether fields bind to loggers (context objects), and what a suppressed message may cost (the hot-path rule). Pin those and the design is half-made; skip them and you'll rediscover each one as a flaw.

Enjoying the preview?

Create a free account to unlock the rest of this course, the in-browser judge, and live AI mock interviews.

Sign up free to continue