Skip to main content
This page explains the deployment_diff object that the get snapshot endpoint returns for every artifact in an environment snapshot: how Kosli picks the artifact it compares against, why there is one answer per flow, and when the value is null. The field descriptions themselves are in the endpoint’s response schema; this page covers the semantics behind them.

Two kinds of diff

Kosli answers two different “what changed” questions about an environment. They are easy to confuse because both are called a diff. The first is a set difference between two points in time. The second is a pointer from a running artifact back to its predecessor, and it is the one to read for lead-time and change reporting. The rest of this page is about the second.

How a snapshot records change

Kosli creates a new snapshot only when the reported set of running artifacts differs from the latest snapshot. An artifact is identified by its fingerprint (its SHA-256 digest), not its name. When a fingerprint appears that was not in the previous snapshot, Kosli records a started event for it; when one disappears, an exited event. The name is recorded alongside, but it carries no identity: web:cbe481c and web:236898f are two different artifacts because their fingerprints differ, and two containers with different names but the same digest are the same artifact. deployment_diff is computed from these started events, not from snapshot numbering.

What “previous” means

deployment_diff hangs off the current artifact and points backwards. Within a flow, the previous artifact is the one that:
  1. was also reported into the same flow,
  2. has a different fingerprint, and
  3. started running in this environment most recently before the current artifact started.
If the current artifact was reported with a template_reference_name, the match is further restricted to artifacts with the same template_reference_name. This is what keeps a multi-service environment honest: the web container is compared against the previous web container, not against whatever else deployed around the same time. Three consequences follow:
  • It is not the artifact in the previous snapshot. Snapshots are created whenever anything in the environment changes, including other services. The match is driven by start events, so a deploy of another service does not make an artifact’s deployment_diff go stale or disappear.
  • It is not matched on name. previous_artifact_name is reported separately because the predecessor may have run under a different name, which is normal when the tag carries the commit.
  • It is anchored to when the current artifact started, not to when you make the request. Every artifact in the latest snapshot still carries the diff describing what it replaced when it started, and the value is stable for as long as the artifact keeps running.

One answer per flow

An artifact can be reported into several flows: a build flow, a promotion flow, a scanning flow. Each entry in artifacts[].flows[] carries its own deployment_diff, computed independently using only artifacts reported into that flow. The public cyber-dojo organization shows this. Its web image is reported into four flows, and the latest aws-prod snapshot returns four different answers for the same running image: Two separate things are happening:
  • Different flows can pick a different previous artifact. Three flows agree the predecessor was 36ad0020. snyk-aws-prod-per-artifact picks 29c69c2f because 36ad0020 was never reported into that flow, so the search skipped further back to the last image that was.
  • Even when they agree on the artifact, they disagree on the commit. git_commit is recorded per flow, and each flow here tracks a different repository. The same image is commit 236898f of cyber-dojo/web to the build flow and commit 30111f1 of the scanning repository to the Snyk flows. previous_git_commit and diff_url describe that flow’s repository, not the image in the abstract.
To answer “what source code changed”, read the entry for the flow that builds the artifact. The other entries answer a real question, but a different one, and can be degenerate: the promotion flow compares 7494758 against itself because the promotion repository did not move between the two promotions.

The top-level field is flows[0]

deployment_diff appears twice in each artifact:
  • artifacts[].deployment_diff, at the top level, and
  • artifacts[].flows[].deployment_diff, one per flow.
The top-level field is a verbatim copy of flows[0].deployment_diff, kept for convenience and backwards compatibility. It is not an aggregate and does not pick the most relevant flow; it reflects stored order.
If your artifacts are reported into more than one flow, read flows[] and select the flow you mean by flow_name. Do not build on the top-level copy.
For a single-flow artifact the two are identical and the top-level field is all you need.

When it is null

deployment_diff is always present in the response. When there is nothing to compare against, the value is null. That happens when:
  • The artifact has no provenance. Something is running that was never reported to a flow, so there is no history to search.
  • Nothing from this flow has run here before. The first deploy of a service into an environment has nothing to diff against.
  • No start event can be resolved for the current artifact before this snapshot, an edge case in older data.
When it is not null, every sub-field is present. previous_trail_name and previous_template_reference_name can individually be null for artifacts reported before trails and templates existed. diff_url can be an empty string (see below). The remaining fields always have a value.

Three caveats

  • previous_running is about this snapshot, not history. false means the predecessor is gone, the normal steady state after a deploy completes. true means both versions are present in this snapshot at once: a rolling deploy caught mid-flight, a canary, or a partially drained service.
  • previous_artifact_compliance_state is evaluated when you make the request, not frozen at snapshot time. If someone attests evidence against the older artifact tomorrow, this field can change for a snapshot taken today. Compliance is a live judgment about an artifact, not a historical record of the deploy.
  • diff_url can be "". It is built by matching the commit URL against GitHub, GitLab, Bitbucket, and Azure DevOps. Any other git host produces an empty string rather than a broken link. previous_git_commit and the artifact’s own git_commit are still there, so you can build the link yourself.

See it yourself

cyber-dojo is a public organization, so no API token is needed:
-1 is the latest snapshot. The other snapshot expressions (#N, ~N, @{...}) are listed on the get snapshot page. For a private organization, authenticate with your API token.
Last modified on September 11, 2026