Live coding · 14 min read

Mobile live coding interview: what to say while you type

How a mobile live coding round is scored, a 45-minute plan, what to say at each stage, a worked Swift example, and how to recover when you stall.

The live coding round is the one where good engineers fail for reasons that have nothing to do with engineering. They know how to build the thing. They have built harder things. Then someone watches their screen, the silence gets longer, and the interviewer’s notes say “struggled to make progress” about a person who would have finished it in twenty minutes alone.

The round is not scored on whether the code works at minute 45. It is scored on what the interviewer could see of your thinking along the way. This guide is about making that visible.

What is scored

When I run a live coding round, my notes have five headings. Correct final code is one of them, and not the heaviest.

What I note Strong Weak
Clarification Asks two or three questions that change the design, then starts Starts typing at once, or asks ten questions to delay
Plan States the approach in a few sentences before coding Discovers the approach by typing
Progress Something runs early, then grows Everything at once, nothing runs until the end
Narration I always know what they are doing and why Long silences, or a stream of “um, so, let me just”
Recovery Names the problem, steps back, tries again Keeps typing faster, or goes quiet
Testing Checks edge cases without being asked “I think it works”

A candidate who finishes 80% of the problem with clear narration and a sensible plan usually scores higher than one who finishes it silently. I have written both reports many times.

The 45 minutes, planned

Minutes Stage What you say
0 to 4 Clarify “Before I start, two questions: …” Then restate the problem in one sentence.
4 to 8 Plan “My approach: … I will start with …, then …, and test with …”
8 to 25 Build the core Narrate decisions, not keystrokes. Run something by minute 15.
25 to 35 Edge cases and tests “What happens when the list is empty? When the network fails?”
35 to 42 Improve “If I had more time, I would …” Pick one improvement and do it.
42 to 45 Wrap up Summarise what works, what does not, what you would do next.

The times are a guide, not a script. The point is that each stage exists. The most common failure is skipping the plan: the candidate starts coding at minute one and spends minute twenty discovering they chose the wrong structure.

Clarifying questions that earn points

Good clarifying questions change what you build. Bad ones only delay.

  • Good: “Should this handle requests arriving from several threads, or only the main thread?” (Changes whether you need synchronisation.)
  • Good: “Is it fine to keep everything in memory, or does it need to survive a restart?” (Changes the storage.)
  • Good: “Can I use the standard library and Foundation, or should I avoid them?”
  • Weak: “What language should I use?” when the job is for iOS.
  • Weak: “What is the expected output format?” when the prompt showed it.

Two or three good questions, then a one-sentence restatement: “So: a rate limiter allowing N calls per window, in memory, single-threaded for now.” That sentence is the first thing I write in my notes when a candidate does well.

Narration: decisions, not keystrokes

Narrating is not reading your code aloud. “Now I’m typing func allow” is noise. Narrate the decisions:

  • “I’ll store timestamps in an array. It’s simple and the limit is small; if the limit were large I’d use a ring buffer.”
  • “I’m passing now in as a parameter so I can test this without waiting for real time.”
  • “This is quadratic in the worst case. For a limit of three it doesn’t matter. I’ll note it and move on.”

The third kind of sentence, where you name a weakness and move on deliberately, is one of the strongest signals in the round. It shows judgement: you saw the problem and chose not to spend time on it.

A worked example

Prompt: “Write a rate limiter that allows at most N calls in any rolling time window.”

After clarifying (in memory, single-threaded, N and window configurable), the plan in three sentences: keep the timestamps of accepted calls; on each call, drop timestamps older than the window; accept if fewer than N remain. Pass the current time in, so tests are deterministic.

import Foundation

struct RateLimiter {
    private let maxCalls: Int
    private let interval: TimeInterval
    private var accepted: [Date] = []

    init(maxCalls: Int, per interval: TimeInterval) {
        (self.maxCalls, self.interval) = (maxCalls, interval)
    }

    mutating func allow(at now: Date = Date()) -> Bool {
        accepted.removeAll { now.timeIntervalSince($0) >= interval }
        if accepted.count >= maxCalls { return false }
        accepted.append(now)
        return true
    }
}

var limiter = RateLimiter(maxCalls: 3, per: 1)
let start = Date(timeIntervalSince1970: 0)
let results = (0..<5).map { limiter.allow(at: start.addingTimeInterval(Double($0) * 0.1)) }
assert(results == [true, true, true, false, false])
assert(limiter.allow(at: start.addingTimeInterval(1.0)) == true)

This compiles and the asserts pass (Swift 6.3.2, Swift 6 language mode). What the interviewer will ask next, and what a senior answer says:

  • “Is >= or > right at the window boundary?” Say which you chose and why. Here a call exactly one window later is allowed. Either is defensible; not having thought about it is not.
  • “Make it thread-safe.” Turn it into an actor, or protect it with a lock. The actor version changes the call site to await, and you should say that out loud, because it changes every caller.
  • “A million calls per second.” The array scan is now the problem. A fixed-size ring buffer, or a token bucket that stores a count and a timestamp instead of every call, trades exactness for constant memory.

That last follow-up is the changed constraint. The round is often decided by whether your answer changes there, and whether you can say what the new design gives up.

When you stall

Everyone stalls. What is scored is what you do in the next thirty seconds.

  1. Say that you are stuck and where. “I’m not sure how to handle the boundary here.” Silence is the only wrong move.
  2. Shrink the problem. “Let me get it working for one call first.”
  3. Use a concrete example. Write out three inputs and the expected outputs as a comment, then make the code match them.
  4. Ask a precise question if you need to. “Would it be fine to assume timestamps arrive in order?” A precise question is not a weakness. “Can you give me a hint?” after two minutes of silence is.

When the hint comes, read how strong it is. A question (“what if the second response lands before the first?”) points at a bug or a missing requirement: stop and answer that exact case before you type. A suggestion (“you could keep the previous task”) is one to apply and credit: “Right, holding the handle lets me cancel it.” A correction (“that crashes on an empty list”) is not one to defend: trace the case they named, confirm it fails, fix it. A hint you use well costs little. The response that costs you is nodding and carrying on down the old path, because it tells me working with you is expensive.

Interviewers want you to pass; most will help if they can see where you are. They cannot help someone who has gone quiet.

Mobile-specific traps

Mobile live coding rounds often use a platform exercise instead of an algorithm: build a small list screen, fetch and show data, add search. The traps are different.

  • Starting with the UI. Get the data model and the fetch working first, printed to the console. Then draw it.
  • Ignoring the main thread. Say where each piece of work runs. On iOS, UI updates on the main actor; on Android, collection in a lifecycle-aware scope.
  • No error state. The network will fail. One line of error handling, mentioned out loud, is worth more than a polished loading animation.
  • Fighting the environment. If the simulator or emulator misbehaves, say so and move on with a stub. Nobody is scoring your Xcode setup.

Live coding interview questions for mobile

The tasks change by platform, and so does what the interviewer grades under them. These are the ones that recur, with where each is covered in depth.

Platform Tasks that recur What they are really testing In depth
iOS Search as you type, an image loader for a feed, a paginated list, token refresh under concurrency Stale results, cancellation, in-flight deduplication The iOS coding interview
Android A paged list, an offline cache, search with debounce State across a configuration change, main-thread work, coroutine scope The Android coding interview
Flutter Machine coding: a small working feature with a mock API, and a state choice made under the clock Structure in the first minutes, rebuilds and keys The Flutter coding interview
Any platform A rate limiter, an LRU cache, a debounce function Complexity you can state, a changed constraint, a trace before “done” The worked example on this page

Those pages cover what each platform asks. This page covers how to behave while you type, which is the same everywhere.

Live coding interview preparation without a partner

Record yourself solving a small problem while narrating to nobody. Watch it back once and count the silences longer than ten seconds. That count is your number, and the goal is to reduce it. Do this three times and the difference is usually obvious. The mobile guides for iOS and Android cover the technical content you will be narrating about.

Pair programming rounds, where the interviewer codes with you, reward the same habits with more conversation, and add one of their own: weighing the interviewer’s suggestions instead of accepting all of them. That round has its own guide.

Sources

Free guide: the Phoenix Method