In a TeamCity build chain, how does a snapshot dependency differ from an artifact dependency between two build configurations?
answer
- Two independent edge types, not one
- Snapshot means order plus same revision
- Artifacts move files, nothing else
- Missing snapshot: files from another build
- Reuse depends on revision consistency
basics
~20 sA snapshot dependency orders the builds and pins them to one source revision, forming the chain. An artifact dependency copies files produced by the upstream build into the downstream one. They are independent settings, and most real chains declare both between the same pair.
solid answer
~50 sTeamCity composes work from separate build configurations rather than stages in one file, and it wires them with two distinct dependency types. A **snapshot dependency** says "this build cannot start until that build finishes, and both must be built from the same snapshot of the sources" — that revision consistency is what makes a chain a chain, and it is what lets TeamCity reuse a suitable finished build instead of rerunning it. An **artifact dependency** says "before this build starts, download these files from that build", governed by artifact rules such as `+:target/*.jar => libs`. Declaring only an artifact dependency is legal and is the classic trap: with no snapshot dependency the source build is resolved by a rule such as last finished build, so a deploy can pick up binaries from a revision it was never triggered for.
code
kotlin · 20 linesobject Deploy : BuildType({
name = "Deploy"
steps {
script {
scriptContent = "./deploy.sh libs/service.jar"
}
}
dependencies {
dependency(Build) {
snapshot {
onDependencyFailure = FailureAction.FAIL_TO_START
}
artifacts {
artifactRules = "+:target/*.jar => libs"
}
}
}
})go deeper
Be able to say TeamCity links separate build configurations into a chain, and that one dependency type controls order while another moves the files the next build needs.
Explain both edges precisely: a snapshot dependency gives ordering plus a shared source revision, an artifact dependency copies published files by artifact rules, and real chains usually declare both.
Diagnose the failure: an artifact dependency without a snapshot dependency resolves to some other build's output, so a deploy ships a binary from a revision nobody triggered. Explain how revision consistency makes build reuse safe.
Own the chain topology — how far to fan out, where composite builds give a meaningful status boundary, and how reuse of already-built nodes keeps a large graph affordable without weakening the build-once guarantee.
## A different composition model Most CI tools let you write a pipeline as an ordered list of stages inside one file. TeamCity's unit is the **build configuration**: a first-class object with its own history, parameters, triggers, artifacts and agent requirements. A pipeline is therefore not a list — it is a graph of build configurations linked by dependencies, and TeamCity calls that graph a **build chain**. Triggering the tip of the chain triggers everything it depends on. Two kinds of edges build that graph, and confusing them is the single most common TeamCity misunderstanding. ## Snapshot dependency: ordering plus one revision A snapshot dependency from `Deploy` to `Build` means two things at once: 1. **Ordering.** `Deploy` will not start until `Build` finishes. 2. **Revision consistency.** Every build in the chain runs against the *same* snapshot of the VCS sources. If three commits land while the chain is running, the downstream builds still use the revision the chain started from, not the newest head. That second property is the reason snapshot dependencies exist. Without it, a chain of five configurations could each check out a slightly different commit, and the artifacts you deploy would not correspond to the sources you tested. Revision consistency also enables **reuse**: if a suitable finished build already exists for that exact snapshot, with the same parameters, TeamCity can attach it to the new chain instead of rebuilding. That is what makes chains cheap in a monorepo where most of the graph is unchanged. Snapshot dependencies also carry failure behaviour. You choose what happens when the upstream build fails or is cancelled — typically the dependent build does not start at all, and the whole chain is marked failed: ```kotlin dependencies { dependency(Build) { snapshot { onDependencyFailure = FailureAction.FAIL_TO_START onDependencyCancel = FailureAction.CANCEL } artifacts { artifactRules = "+:target/*.jar => libs" } } } ``` ## Artifact dependency: files, not ordering An artifact dependency is about **bytes**. Before the dependent build's steps run, TeamCity downloads files published by the source build into the dependent build's checkout directory, according to artifact rules. A rule has the form `+:<source pattern> => <target directory>`, with `-:` to exclude; archives can be unpacked by referencing a path inside them. Crucially, an artifact dependency does **not** by itself say which build to take the files from. It is resolved by a rule — the last finished build, the last successful or pinned build, a build with a given tag, or *the build from the same chain*. The last option is the one you want in a pipeline, and it only exists meaningfully when a snapshot dependency ties the two configurations into one chain. ## The failure this produces The realistic incident looks like this. A `Deploy` configuration has an artifact dependency on `Build`, taking the last successful build's JAR, but no snapshot dependency. Someone triggers `Deploy` to ship the fix they just merged. Meanwhile a later commit has already produced a newer successful `Build`. `Deploy` happily takes *that* JAR. Nothing errors; the deployed binary is simply not the change anyone thought they were shipping, and the chain shows green. The fix is to add the snapshot dependency so the pair forms a chain and the artifacts resolve to that chain's build. The symmetrical mistake is a snapshot dependency with no artifact dependency: the ordering is right, the revision is right, and the downstream build then rebuilds the module from source because nothing handed it the binary. It works, it is slow, and it quietly abandons the build-once discipline — the thing you deploy is not the thing you tested. ## Composite builds and chain shape Because each node is a real configuration, chains fan out naturally: one `Build` with several test configurations depending on it, and a single downstream node depending on all of them. TeamCity also offers a **composite** build configuration — one that runs no steps and occupies no agent, existing purely to aggregate the status of its dependencies into a single green or red result you can trigger, watch, or attach a status check to. ## What to say in an interview Name the two edges, state that snapshot is ordering *and* revision consistency while artifact is file transfer, note that they are orthogonal and usually declared together, and give the failure mode: an artifact dependency without a snapshot dependency resolves to some other build's output. If you can add that revision consistency is what makes build reuse safe, you have covered the model.
- What does artifact rule syntax like +:target/*.jar => libs actually do?It selects files from the source build's published artifacts and places them in the dependent build's checkout. `+:` includes, `-:` excludes, the pattern is matched against artifact paths, and everything after `=>` is the target directory created in the dependent build. Paths inside published archives can be referenced too, so a zip can be unpacked selectively.
- Why can TeamCity reuse an already-finished build inside a new chain?Because a snapshot dependency pins the chain to one source revision, TeamCity can tell that an existing finished build ran on exactly that revision with the same parameters. If so, it attaches that build to the new chain rather than rerunning identical work — the saving that makes large chains practical.
- What is a composite build configuration used for?It runs no build steps and takes no agent. It exists to aggregate the results of the configurations it depends on into one status you can trigger and watch, so a chain of many parallel builds presents as a single green or red node instead of forcing people to inspect each one.
saying these in an interview costs you the question
- Thinks an artifact dependency implies build ordering
- Believes a snapshot dependency copies files downstream
- Assumes every build in a chain checks out the newest commit
- Wires deploy to "last successful build" and calls it a pipeline
- Treats build configurations as stages inside one pipeline file