Caching
When template apply fetches a template from a GitLab source, deckctl extracts
it to a local cache so the next apply doesn’t re-download the archive. Local
sources never cache — there is nothing to fetch.
The cache is per-user, lives on the filesystem, and is safe to delete at any time.
Where it lives
Section titled “Where it lives”Resolved in this order, first match wins:
--cache-dir <path>DECKCTL_CACHE_DIR$XDG_CACHE_HOME/deckctl/~/.cache/deckctl/
deckctl template apply my-template ./out --source work --cache-dir /tmp/deckctl-cacheDECKCTL_CACHE_DIR=/srv/shared-cache deckctl template list --source workWhat’s on disk
Section titled “What’s on disk”Entries are keyed by source name, template name and ref:
~/.cache/deckctl/ .staging/ # temporary staging for atomic writes work/ # source name from config.yaml go-service/ # template name (the GitLab project slug) v1.2.3/ # ref — a tag or a branch name main.go.tmpl deckctl.yaml meta.json # cache metadata, not part of the template main/ ...Because the ref is part of the key, v1.2.3 and v1.3.0 of the same template
coexist rather than evicting each other.
meta.json records when the entry was fetched, when it was last verified, the
server’s ETag, and the source URL. deckctl manages it; don’t hand-edit it.
How freshness is decided
Section titled “How freshness is decided”Each entry tracks two timestamps:
fetched_at— when bytes were last actually downloadedlast_checked— when the entry was last verified against the server (freshly downloaded, or confirmed unchanged by a304)
On every apply:
- Is there an entry for this source/template/ref?
- Is
last_checkedwithin the TTL? (Default: 1 hour.)
Both yes → the cached files are used with no network call for the archive.
Otherwise deckctl sends a conditional request carrying the stored ETag
(If-None-Match):
| Server responds | Result |
|---|---|
304 Not Modified | Cached bytes are still current; last_checked bumped to now |
200 OK | New content; the entry is atomically replaced along with the new ETag |
A full archive download only happens when the upstream template genuinely changed.
Per-source TTL
Section titled “Per-source TTL”sources: - name: work type: gitlab url: https://gitlab.com group: platform/templates cache_ttl: 24h # check upstream at most once a daycache_ttl uses Go duration syntax: 30m, 2h, 1h30m, 90s. Omitted
means 1h.
A negative cache_ttl is rejected at config load, and setting cache_ttl on a
local source is rejected too.
Bypassing the cache
Section titled “Bypassing the cache”--no-cache forces a fresh unconditional fetch for a single apply:
deckctl template apply my-template ./out --source work --no-cacheThe result is still written to the cache, so the next apply is fast again. Use it when you suspect the cache is stale — for example after an upstream force-push that didn’t move the ETag.
Inspecting
Section titled “Inspecting”deckctl cache list┌────────┬────────────┬────────┬──────────┬───────┐│ Source │ Template │ SHA │ Size │ Age │├────────┼────────────┼────────┼──────────┼───────┤│ work │ go-service │ v1.2.3 │ 2.1 MB │ 5m12s ││ work │ helm-chart │ main │ 880.5 KB │ 1h32m │└────────┴────────────┴────────┴──────────┴───────┘- SHA — the ref: a tag or branch name. (The column name is historical; it is not necessarily a commit SHA.)
- Age — time since
last_checked, i.e. how long since deckctl last verified this entry.
-o json emits the full metadata including etag, fetched_at,
last_checked, source_url and the on-disk path.
Clearing
Section titled “Clearing”# Everything, with a confirmation promptdeckctl cache clear
# Narrow it down — filters compose with ANDdeckctl cache clear --source workdeckctl cache clear --template go-servicedeckctl cache clear --older-than 1w
# Combine, and skip the promptdeckctl cache clear --source work --older-than 30d --auto-approve--older-than accepts a single number plus one unit from s, m, h, d,
w, and decimals are fine (0.5h). It is compared against last_checked.
Deleting the cache directory with rm -rf is equally safe — deckctl rebuilds
what it needs on the next apply.
Concurrency
Section titled “Concurrency”deckctl assumes a single-user CLI workflow. Two simultaneous applies against the same cache directory are not synchronised: the atomic-rename write prevents partial-write corruption, but one of the two may re-fetch instead of reusing the in-flight write. For normal use this is invisible.
Troubleshooting
Section titled “Troubleshooting”| Symptom | Fix |
|---|---|
| Template seems stuck on an old version | --no-cache once, or deckctl cache clear --source X --template Y |
| Cache directory growing | deckctl cache list to see sizes; deckctl cache clear --older-than 30d to prune |
Changed cache_ttl but still getting the old version | TTL is measured from last_checked, not fetched_at. Force with --no-cache |
cache_ttl: 1d errors on load | Use 24h — Go duration syntax has no day unit |