Staging, Shared Filesystems, and Data Locality¶
Many production failures are blamed on "the cluster" or "Snakemake being weird" when the real issue is simpler:
the repository never stated what it assumes about where files live and when they become visible.
This page is about making those assumptions explicit.
How to read this page¶
Read this page with one boundary question in mind:
which paths are temporary operating context, and which paths are the stable contract the workflow is promising to produce?
If you keep that question visible, staging and filesystem behavior stop sounding mystical and start sounding reviewable.
Why this lesson belongs in Module 03¶
By Module 03, the workflow already has meaningful outputs and publish surfaces. That is exactly why locality matters now.
If the repository does not separate temporary placement from final trust surfaces:
- incidents get explained as cluster folklore
- scratch paths start acting like accidental contracts
- local and CI differences feel haunted rather than owned
Data locality is an operational boundary¶
The workflow meaning may be unchanged while the operating context changes:
- local filesystem
- CI workspace
- shared cluster filesystem
- scratch or staged working directory
Those contexts can differ safely, but only if the repository treats them as policy surfaces instead of invisible background facts.
A strong beginner habit¶
When a run behaves differently across environments, ask about path roles before you ask about Snakemake.
For example:
- where is the job reading from
- where is it writing temporary work
- when is it publishing to the declared final output
The two questions to ask first¶
When an output "goes missing" or appears late, ask:
- where was the job really writing
- when should another process be allowed to trust that write
Those questions are often more useful than staring at one failed command.
The common beginner mistake¶
People often collapse these questions into one vague thought:
the file should be there somewhere.
That is exactly the mindset this page is trying to replace.
Shared filesystems add timing pressure¶
On a shared filesystem, a job may finish before another process sees the output immediately. That does not mean the workflow semantics changed. It means the operating context needs an explicit patience policy.
This is where settings such as latency handling belong:
- they acknowledge the storage model
- they remain operational rather than semantic
- they help the workflow remain honest under normal infrastructure lag
That is a legitimate profile concern.
A quick self-check before you keep reading¶
Imagine a shared filesystem where a finished output appears a little later to another process.
Did the workflow meaning change?
No. The storage visibility policy changed. That is why latency handling belongs on the operational side of the boundary.
Scratch and staging are not semantic detours¶
Teams often stage work to local scratch or temporary directories for good reasons:
- faster local IO
- reduced pressure on shared storage
- simpler cleanup during execution
That can be healthy. It becomes dangerous when the repository stops answering:
- which paths are temporary
- which path is the final trusted publication surface
- how staged outputs become durable outputs
Staging is safe only when the final contract remains clear.
One healthy mental model¶
flowchart LR
input["declared input surface"] --> work["temporary work area or scratch"]
work --> final["declared final outputs"]
final --> publish["published contract surface"]
This model matters because it keeps three roles separate:
- where work happens
- where final workflow outputs live
- what downstream users are allowed to trust
When those collapse into one vague directory story, incidents get harder to explain.
A weak staging habit¶
Weak operational habit:
- write directly to whatever path is convenient on the current machine
- move files around ad hoc when the scheduler changes
- let each maintainer decide whether scratch is used
This creates repository behavior that feels situational rather than intentional.
The repository may still run. Another maintainer will not know which path story to trust.
A stronger staging pattern¶
Healthy staging design usually has these properties:
- the final output path is still the declared contract
- temporary or scratch paths are clearly operational
- publication into the final path is deliberate
- profiles or operating docs explain the context difference
This keeps the workflow semantics stable even while the operating context changes.
Extend the scheduler receipt with a storage question¶
The scheduler-policy specimen records CPU, memory, and runtime. That is enough to review resource translation, but not enough to execute a real job. A reviewer must ask one more question:
From the allocated worker, how does each declared path become reachable?
Complete this table for a deployment:
| Path role | Example | Worker access | Publication rule |
|---|---|---|---|
| immutable input | data/records.tsv |
shared read-only mount | never modified |
| scratch work | node-local allocation | worker-local | removed after success |
| declared result | results/summary.tsv |
shared project storage | atomic rename |
| audit evidence | artifact bundle | CI or reviewer storage | immutable per run |
Do not write “shared filesystem” in the worker-access column. Name the mount, object-store transfer, or staging command that makes the path reachable. Vague storage nouns hide the exact boundary that fails during deployment.
Trace a staged scheduler job¶
sequenceDiagram
participant O as Orchestrator
participant S as Scheduler
participant W as Worker scratch
participant P as Project storage
O->>S: submit resources and path policy
S->>W: allocate worker
P->>W: stage declared inputs
W->>W: compute and validate temporary result
W->>P: atomically publish declared output
P-->>O: output visible at contract path
Each arrow needs evidence:
- submission receipt for orchestrator to scheduler;
- scheduler job ID for allocation;
- transfer log or mount record for input availability;
- command log and validation result for computation;
- checksum or manifest for publication;
- Snakemake completion state for the final contract path.
If a deployment cannot produce one of those records, say which claim remains untested. Do not replace the missing evidence with “works on our cluster.”
Decide where a failure belongs¶
Consider four incidents:
- The scheduler rejects
--mem=8000M. - The worker cannot see
data/records.tsv. - The command succeeds but the final rename is delayed.
- The published result contains the wrong records.
They belong to different owners:
| Incident | Primary boundary | First evidence |
|---|---|---|
| request rejected | scheduler policy | submission stderr |
| input invisible | staging or mount policy | worker path probe |
| rename delayed | shared-storage consistency | publication log and latency |
| wrong records | workflow semantics | result content and threshold |
Only the third case may justify increasing latency-wait, and only after showing
that the writer completed and visibility lagged. Increasing latency for the
other cases merely delays a useful failure.
Preserve one final-path invariant¶
Across local, CI, and scheduler contexts:
must remain the declared output. Scratch locations may differ. Transfer tools may differ. The path that downstream rules trust must not silently change.
That invariant lets the DAG preserve meaning while profiles vary execution:
flowchart TD
L["local temporary directory"] --> F["results/summary.tsv"]
C["CI workspace"] --> F
S["scheduler scratch"] --> F
F --> V["content verification"]
V --> D["downstream dependency"]
The arrows are context-specific policy. The final node is the workflow contract.
What a good explanation sounds like¶
Strong:
The workflow may use scratch differently by context, but it still publishes into the same declared final paths, so the trust surface does not drift.
Weak:
On the cluster, the file story is just different.
What should stay out of workflow meaning¶
The following often belong in policy rather than workflow meaning:
- latency expectations
- scratch or staging location
- executor-facing storage behavior
- log-location conventions for one operating context
The following usually do not belong purely in policy:
- which files count as final outputs
- whether a file is part of the publish boundary
- which sample identities the workflow is meant to process
That is the same module boundary in a new setting.
Common failure modes¶
| Failure mode | What it looks like | Better repair |
|---|---|---|
| shared-filesystem lag is treated as random workflow failure | reruns feel arbitrary | make latency handling explicit in policy |
| scratch usage changes the apparent final path story | maintainers cannot tell what is durable | keep final outputs and scratch paths separate |
| local and CI use different path assumptions without review | one context works and the other feels haunted | document and encode the context difference in profiles or operation docs |
| staging hides partial publication | files appear in final locations too early | keep publication explicit and deliberate |
| temporary paths become accidental contracts | downstream tools start depending on scratch layout | reserve stable trust only for declared final outputs |
The explanation a reviewer trusts¶
Strong explanation:
the workflow may stage work in a context-specific scratch area, but the final outputs are still published into the same declared contract paths; profile settings handle latency and execution context, while publish and results paths remain semantically stable.
Weak explanation:
on the cluster we write files somewhere else first because that is just how it works.
The first explanation gives a boundary. The second gives a habit without a contract.
End-of-page checkpoint¶
Before leaving this page, you should be able to:
- explain why data locality is an operational boundary
- describe one legitimate policy use for latency handling
- distinguish scratch space from final output contracts
- explain one staging design that keeps workflow meaning stable across contexts