skip to content

A one-time flash message sometimes never appears and sometimes shows on the wrong page. How do you diagnose it?

level: seniorimportance: should knowfreq 44%

answer

  1. something else consumed the hop
  2. count the requests between write and render
  3. log write, read and sweep with request ids
  4. polls and asset fetches are requests too
  5. no read line means the write never persisted

basics

~20 s

Both symptoms mean a request other than the intended page consumed the entry. Log every flash write, read and sweep with a request identifier, then find which request landed between the write and the page.

solid answer

~40 s

A flash entry survives exactly one following request, so anything that slips into that slot steals it. Instrument first: log the write and the read with a request identifier, the path, and the session identifier, then order them for one failing case. The usual culprits are a redirect chain of two hops where the intermediate request consumes the entry, a background poll or asset fetch handled by the framework arriving between the redirect and the page, a second tab sharing the one session, and a write whose session was never saved so nothing was there to read. The fix is to shorten the hop chain, keep incidental requests off the session, or carry the outcome explicitly in the redirect target rather than relying on the one-hop slot.

go deeper

for a junior

Hold on to the contract: one write, one following request, then gone. If a message goes missing, ask what other request could have arrived first rather than assuming the feature failed.

for a middle

Be able to list the plausible consumers of the hop — a second redirect, a background call, another tab — and say where you would log the write, the read and the sweep to tell them apart.

for a senior

Lead with instrumentation and sequencing, name sweep-on-read versus end-of-request sweeping as the behaviour that decides which causes are possible, and propose a structural fix rather than reflashing.

for a principal

Treat it as an argument about channel guarantees: a single-hop best-effort slot is fine for cosmetics and wrong for anything load-bearing, and that boundary should be a stated convention, not per-feature discovery.

## What the two symptoms already tell you A flash entry is written on one request and removed after the next. Two failure shapes follow directly from that contract: - **Never appears** — either the entry was never persisted, or some request other than the page consumed it first. - **Appears on the wrong page** — the entry was persisted, and the request that read it was not the one you expected. Both are the same defect seen from different sides: *the request that consumed the hop was not the request you meant*. That framing keeps the investigation short, because it turns the question into "which requests arrived between the write and the page, and did any of them touch the session?". ## Instrument before theorising Add three log lines, each carrying a request identifier, the path, the method and the session identifier: 1. when a flash entry is written; 2. when the framework hands one to a handler or template; 3. when the framework sweeps the entry. Then take one failing case and sort by time within that session identifier. In practice the sequence itself names the cause: a path you did not expect appears between the write and the page, or the read line is missing altogether. ## The candidate causes, in the order they occur | Cause | Signature in the log | Fix | |---|---|---| | Two redirect hops | write, then an intermediate path, then the page with nothing | reduce to one redirect, or re-mark the entry for another hop | | A background or polling request | an unrelated path between the redirect and the page | keep those endpoints off the session entirely | | An asset or icon request routed through the framework | a static-looking path in the middle | serve those outside the framework's session handling | | A second tab or window | reads from two different pages interleaved | scope the message to something the target page identifies | | The writing request's session never saved | no read line at all, and no entry in the store | check the dirty flag and the save path for that request | | The handler rendered instead of redirecting | the message surfaces on a much later, unrelated page | only write flash immediately before a redirect | Two of these deserve emphasis. A **poll or prefetch** is invisible in a manual test and constant in production, which is exactly why the bug is intermittent and unreproducible on a developer machine. And the **session-never-saved** case is not a flash bug at all — the entry is stored with the session, so whatever prevented that write, from a skipped write-back to a failing store, takes the message with it. ## Narrowing it down quickly - Reproduce with a client that issues **no** extra requests, in one tab, and confirm the message appears. If it does, something else in the real client is consuming the slot. - Compare the failing path's redirect chain: count hops between the write and the render. - Check whether the sweep is on read or at end of request. Under end-of-request sweeping, **any** request from that client burns the hop, even one that never looked at the message; under sweep-on-read, only a request that actually read it does. - Look for framework-handled paths that should not be: health checks, manifests, icons, telemetry endpoints. Each is a request, and a request is a hop. ## Designing the problem away Once diagnosed, prefer a structural fix over a reflash sprinkle: 1. **One redirect, then render.** Chains of redirects make the one-hop contract unpredictable. 2. **Keep incidental traffic off the session.** If an endpoint has no reason to read session state, it should not; that alone removes the poll and asset causes. 3. **Do not put anything load-bearing in the flash.** It is a best-effort, single-hop channel that the user can drop by closing the tab. 4. **Where the message must be reliable, carry it in the redirect target** as a code the page resolves into text, or re-derive the outcome from the data the page already loads. ## Why this is a senior question It looks like a trivia question about one feature and is really a question about request sequencing. The candidate who answers well does not guess a cause; they say what the contract is, note that the client sends more requests than the page you are watching, and describe the log evidence that would distinguish the causes before touching any code.

  • Why is this bug so much easier to see in production than on a developer machine?
    Real clients emit traffic a manual test does not: background polls, prefetches, telemetry, icon and manifest fetches, and a second open tab. Any of them can occupy the single hop. Locally you click once and see one request, so the message normally arrives.
  • How does sweep-on-read versus sweep-at-end-of-request change which causes are possible?
    Under sweep-on-read only a request that actually reads the entry removes it, so a poll that ignores the session is harmless. Under end-of-request sweeping any following request burns the hop, which makes background traffic a direct cause and the failure much more intermittent.
  • When would you stop using the flash for this message entirely?
    When the message must not be lost — a payment result, a one-time credential, anything the user cannot reconstruct. Then carry an outcome code in the redirect target or re-derive the result from data the page loads, and keep the flash for cosmetic confirmations.
  • The log shows a write but no read and no sweep. What does that point at?
    The entry never reached the store, so the problem is on the writing request, not the reading one. Look at whether that request's session was saved at all: a skipped write-back, an invalidated session, or a store failure will take the message with it.

saying these in an interview costs you the question

  • Blames the browser cache before checking which requests hit the server
  • Adds a reflash call everywhere instead of finding the extra hop
  • Assumes only page requests count toward the one-hop lifetime
  • Thinks two tabs each get their own copy of the flash entry
  • Concludes the store is broken without checking whether a save ever ran