skip to content

After a delivered value set changes, what does a process watching its mounted file actually observe, and when?

level: middleimportance: nice to knowfreq 30%

answer

  1. three clocks, not one
  2. the projection refreshes on a period
  3. built elsewhere, then pointed at
  4. whole old set or whole new set
  5. re-open by path, watch the directory

basics

~20 s

It observes the whole new set appearing at once, not a file being rewritten byte by byte, because the platform builds the content elsewhere and swaps the directory pointer in one step. It observes it after a bounded delay, not immediately.

solid answer

~50 s

The mounted view is refreshed by an agent on the host, not written by the editor, so there is a gap between the value changing at rest and the new bytes appearing under the mount — bounded by whatever refresh period the platform uses, which exists precisely to cap how stale a projection can be. What appears is the complete new set: the agent materialises the content in a new location and swaps the directory's pointer in one step, so a reader either sees the whole previous set or the whole new one and cannot read a half-updated set. Two consequences follow. A process holding an already-open handle keeps reading the old content until it re-opens by path, and a watch registered on the individual file never fires, because that file was replaced rather than modified.

go deeper

for a junior

Know that the mounted copy is refreshed by the platform on its own schedule, so an edit is visible to the process after a short delay rather than the instant it is made.

for a middle

Explain the stacked delays — projection refresh, detection, parse and rebuild — and why the set appears whole: the content is built elsewhere and the directory pointer is swapped in one step.

for a senior

Draw the consequences for real code: watch the directory, re-open by path, never cache the handle, and record adoption time so the real bound on your platform is measurable rather than assumed.

for a principal

Decide which changes may ride propagation at all. Anything that must be simultaneous across a fleet cannot, and pretending otherwise turns a bounded delay into an availability incident.

## Three clocks between the edit and the effect "How long until the new value is live?" is really three questions stacked, and only the last of them belongs to the application. 1. **Edit to visible bytes.** The value changes at rest, and an agent on each host refreshes the projection for the instances that reference it. This is not instantaneous, and it is not meant to be: the refresh period exists to bound staleness at a cost the platform is willing to pay. Platforms choose different periods and different triggers — some refresh on a timer, some react to a notification and use the timer as a backstop — so the honest statement is that the delay is **bounded, not zero**, and its bound is a property of the platform, not of your service. 2. **Visible bytes to the process noticing.** A watch fires, a debounce elapses, or an external reload signal arrives. 3. **Noticing to serving.** The process parses, validates, rebuilds derived state and swaps it in. An engineer who says "the change takes about a second" is usually quoting clock three and ignoring clock one, which is typically the largest of the three. ## Why the set appears whole The agent does not open the mounted file and rewrite it. It materialises the complete new set somewhere else under the mount and then swaps the directory's pointer to it in a single step. That gives a property worth stating precisely: - A reader that opens the path **after** the swap gets the entire new set. - A reader that opened **before** the swap continues to read the entire previous set from the handle it already holds. - **No reader gets a mixture**, even when the set spans several files, because all of them move together. That last point is the reason this shape is used. A configuration split across four files that were rewritten in place could be read as three new files and one old one — a set that was never valid and that no one ever authored. Note the limit of the guarantee: it holds for a set the platform swaps as a whole. A file that some other actor rewrites in place under the same mount can absolutely be read half-written. ## What this does to a watching process | Behaviour | Result after a whole-set swap | |---|---| | Holding an open handle and re-reading from it | Keeps returning the old content indefinitely | | Watching the individual file for modification | Never fires; that object was replaced, not modified | | Watching the containing directory | Fires, because the directory's contents changed | | Re-opening by path on every reload | Reads the current set correctly | So the correct implementation is: **watch the directory, and always re-open by path**. A process that caches a file handle at start-up for efficiency has effectively opted out of propagation without saying so. ## Bounding the total delay honestly For a rate-limit table edited during business hours on a forty-replica gateway, the operator's question is "when is the whole fleet on the new table?", and the answer is the sum of the worst case of each clock, per instance: - clock one is bounded by the platform's refresh period and is paid independently on each host; - clock two is bounded by the debounce plus whatever detection the process uses; - clock three is the parse and rebuild, usually the smallest. Because clock one runs independently per host, instances do **not** cross over together — which is exactly the window in which some replicas answer on the old table and some on the new. ## Practical rules - **Do not treat a mounted value as a synchronous write.** If a change must be simultaneous across a fleet, propagation lag is the wrong tool and a coordinated change is needed instead. - **Do not quote a number you did not measure.** The refresh bound differs by platform and by how the value is delivered; say that a bound exists and what it is for. - **Do not cache the handle.** Re-open by path, or the process will read the same bytes forever. - **Record when the adoption happened**, not when the edit happened. The gap between them is the only way to learn what your platform's real bound is. - **Expect the whole set or nothing.** If you see a genuinely half-updated set, something other than the platform's projection wrote into that mount.

  • Why does a process that kept its file handle open never see the new values, even though its watcher fired?
    Because the handle refers to the content it opened, and the swap replaced what the path resolves to rather than modifying that content. The old bytes remain readable through the existing handle for as long as it is held. The watcher correctly reported a change; the read went to the wrong place. Re-opening by path on every reload fixes it.
  • Is the whole-set swap a guarantee you can rely on for any file under that mount?
    Only for the set the platform projects there and swaps as a unit. A file written into the same mount by something else — a start-up hook, the workload itself, a helper process — is an ordinary write and can be observed half-complete. The guarantee comes from how the projection is published, not from the mount point being special.

A noticeboard whose pages are never edited in place: a complete new set is printed in the back office and the whole board is swapped when it is ready, so no one ever reads three new notices beside one old one.

saying these in an interview costs you the question

  • Calls a delivered value change immediate and synchronous
  • Quotes one platform's refresh period as a universal number
  • Caches the file handle at start-up and re-reads from it
  • Expects all replicas to cross over to the new set together
  • Thinks a half-written read is possible for a whole-set swap