Articles
DVC Interview Questions: Data Versions, Pipeline Dependencies, and Reproducible Runs
Practice DVC interview questions with a missing pipeline dependency, changed parameters, unavailable remote data, and a reproducible recovery checklist.
Your teammate checks out yesterday's Git commit, runs dvc repro, and gets a different model. Is DVC broken? Possibly, but the stronger interview answer first asks which input changed, whether that input was declared, whether the needed data object exists locally or in the remote, and whether the training command itself is deterministic. DVC can track a pipeline's declared dependencies and outputs; it cannot infer every hidden file, external service, package, or random seed that the code uses.
This guide uses a small original repository to practice three different failures: an undeclared code dependency, a changed parameter, and a missing remote artifact. Evidence boundary: current DVC documentation defines commands and metadata behavior; the repository and expected incident responses below are editorial examples. DVC was not installed in this workspace, so command-output wording is described from documentation rather than claimed as a locally executed transcript.
Start with the three layers of reproducibility
Versioning a model means more than saving one .pkl file. Git identifies a code and metadata revision. DVC metadata points to content-addressed data and outputs, which may be in a local cache or configured remote. A pipeline definition connects commands, dependencies, parameters, and outputs so a changed input can trigger the right stages. The environment—Python and package versions, platform, external APIs, seeds, and hardware-specific nondeterminism—still matters. A pipeline can be cache-consistent and scientifically irreproducible if this last layer is uncontrolled.
The official dvc.yaml documentation describes stages, deps, outs, and parameter dependencies. dvc.lock records resolved stage state after reproduction; commit it with dvc.yaml and relevant Git-tracked code. Large data are generally represented by DVC metadata and cache objects rather than committed as ordinary Git blobs. The exact files to check in depend on how the project tracks data, but copying only the YAML without its lockfile and data objects is not a complete handoff.
Distinguish data versioning from pipeline execution. dvc add tracks a data artifact and writes a .dvc file. dvc repro executes changed pipeline stages and updates pipeline state. dvc push transfers cache objects to a remote; dvc pull retrieves them. A successful local reproduction does not imply that a teammate can pull the data from a remote. DVC's push documentation and pull documentation define those separate actions. Also distinguish DVC from a model registry: this exercise concerns reproducible inputs and outputs, not choosing a production alias.
The interview repository: what is declared and what is hidden?
Imagine a repo with a tracked data/raw.csv, a preparation stage, a training stage, and an evaluation stage. The preparation code imports src/normalize.py, but the initial YAML forgets to declare it. Training reads train.seed from params.yaml. Evaluation reads the model and a held-out file. The following abbreviated dvc.yaml is a teaching example; actual scripts and datasets are not included here.
stages:
prepare:
cmd: python src/prepare.py
deps:
- data/raw.csv
- src/prepare.py
# BUG: src/normalize.py is imported but not declared.
outs:
- data/clean.csv
train:
cmd: python src/train.py
deps:
- data/clean.csv
- src/train.py
params:
- train.seed
outs:
- models/model.pkl
evaluate:
cmd: python src/evaluate.py
deps:
- models/model.pkl
- data/holdout.csv
- src/evaluate.py
metrics:
- metrics/quality.json
The declared graph is raw.csv → prepare → clean.csv → train → model.pkl → evaluate → quality.json, with holdout.csv feeding evaluation. The real graph also contains normalize.py → prepare. That missing edge is the failure. The supporting visual makes the difference between declared and actual inputs visible; in an interview, name the omitted file rather than vaguely saying “DVC missed a change.”
Question 1: what happens when an undeclared file changes?
Suppose only src/normalize.py changes. DVC compares declared dependencies, command, parameters, and outputs against recorded state. Because the helper file is absent from prepare.deps, it may report the stage unchanged and skip it on dvc repro, even though the script would produce different clean data if run. That is not proof the old output is correct. It shows the dependency graph is incomplete. The official repro command is designed to reproduce stages whose tracked inputs have changed, not to discover hidden imports.
The fix is to add src/normalize.py to prepare.deps, review any other imports or reference files, and rerun dvc repro. Expect preparation and downstream training/evaluation to be reconsidered because clean data can change. Compare hashes and metrics before and after; do not assume a changed source file necessarily changes output bytes. Update dvc.yaml and dvc.lock together in Git. For a safety check, change a known normalization rule in a disposable branch and see whether dvc status or dvc repro now detects the appropriate stage. dvc status reports differences in declared pipeline state; it cannot certify unlisted dependencies.
Do not use dvc repro --force as a permanent substitute for declaring the missing edge. A forced run can expose the problem once, but future collaborators still have an incorrect graph. Likewise, changing a comment in an undeclared file and observing no rerun does not prove data versioning is broken: DVC was never told to watch that input. Explain the contract and repair it.
Question 2: how should a parameter change propagate?
Now suppose params.yaml changes train.seed, which is listed under the train stage's params. DVC should see the declared parameter dependency change and reconsider training, then evaluation if the model output changes. Preparation should remain unaffected because its declared inputs did not change. This is an important optimization: reproducibility does not mean rerunning every stage for every edit. It means running the stages whose declared state depends on the edit, subject to DVC's run-cache and output behavior.
A seed being tracked does not guarantee byte-identical models. The training script must actually read it and seed each relevant library, and the environment must be controlled enough for the requested level of repeatability. A GPU kernel, shuffled data-loader workers, or an external feature service can add variation. In an interview, separate “DVC recorded the parameter and re-executed the stage” from “the algorithm is deterministic.” If train.seed is declared but never read, DVC may rerun unnecessarily; if it is read but undeclared, DVC may incorrectly skip. Both are design defects, but their symptoms differ.
Ask whether params.yaml itself is tracked in Git and whether the specific nested key in params matches what the script reads. A one-character path mismatch can make the pipeline invalid or track the wrong value. Compare dvc params diff or the Git diff, then dvc status and dvc.lock to explain what changed. Avoid presenting the exact console message as universal across versions; the invariant is the dependency relationship.
Question 3: what if the remote artifact is missing?
A teammate checks out the Git revision but cannot get data/raw.csv because its cache object was never pushed, the wrong remote is selected, credentials lack access, or the object was deleted. dvc pull cannot manufacture an unavailable object from its hash. First distinguish “not in my local cache” from “not in the configured remote.” Check the remote configuration and access, then use DVC's status or pull diagnostics to identify the missing object. If the object exists on another authorized collaborator's cache, that person can push it to the intended remote. If it exists nowhere, the team needs the original source or a documented rebuild path; changing the .dvc pointer to a different file without review would silently change the experiment.
What if the missing object is models/model.pkl instead of raw data? If the declared inputs are present and the stage is reproducible, rerunning training may regenerate an output, although exact bytes can differ for nondeterministic training. If raw input is absent, downstream reproduction cannot start. A DVC remote is an artifact transport and shared cache, not a magical backup of every local run. DVC's status command documents checking workspace and, with cloud options, remote state; choose the command that answers which layer is missing.
Do not put credentials in dvc.yaml, a .dvc pointer, or a blog example. Use the team's secret-management mechanism and a private local configuration for machine-specific access. Record the remote name, object hash, commit, and who verified restoration. After repair, do a fresh checkout on a clean worker, pull required objects, reproduce the pipeline, and compare outputs and metrics to the recorded run. A successful dvc push response alone is not the final proof that a new machine can recover the version.
A compact failure matrix for the interview
| Change or failure | What a healthy graph should show | What to do next |
|---|---|---|
src/normalize.py changes but is undeclared | Preparation may appear clean; this is a false negative in the graph | Declare the helper dependency, rerun, update lockfile |
Tracked train.seed changes | Training is considered, with downstream evaluation as needed | Verify script reads seed; compare outputs and metrics |
| Required raw data object missing locally but present remotely | Pull can restore it | Select correct remote and verify hash/content |
| Required raw data object absent remotely too | Pull fails; training cannot reconstruct it | Find authorized source or rebuild procedure, then push and re-verify |
| Model output object missing but inputs available | Regeneration may be possible | Reproduce and compare, accounting for nondeterminism |
A useful final answer describes the recovery order: identify Git commit, verify DVC metadata and lockfile, resolve remote objects, inspect declared dependencies and parameter keys, run status/repro, and compare produced metrics. If a stage unexpectedly skips, audit hidden inputs before forcing execution. If a pull fails, verify the remote and object rather than editing code. The repair is different because the failure is at a different layer.
Sources and Further Reading
- DVC,
dvc.yamlFiles — official stage, dependency, output, and parameter metadata. - DVC,
repro— official pipeline reproduction behavior. - DVC,
status— official workspace and remote-status checks. - DVC,
pull— official retrieval of remote data/cache objects. - DVC,
push— official transfer of local cache objects to a remote.