Fix "backend exists on a draft version but isn't reachable from the new Compute deploy" bugs after `fastly compute publish`. Use when: (1) You ran `fastly service backend create --autoclone` (or any dashboard/CLI change that creates a draft version) but did not activate that draft, (2) You then ran `fastly compute publish` which appeared successful but your backend / ACL / header / dictionary change is missing from the active version, (3) Compute code returns backend-not-found errors or misro...
Scanned 5/27/2026
Install via CLI
openskills install divinevideo/divine-mobile---
name: fastly-compute-publish-ignores-draft-versions
description: |
Fix "backend exists on a draft version but isn't reachable from the new Compute deploy"
bugs after `fastly compute publish`. Use when: (1) You ran `fastly service backend create
--autoclone` (or any dashboard/CLI change that creates a draft version) but did not
activate that draft, (2) You then ran `fastly compute publish` which appeared successful
but your backend / ACL / header / dictionary change is missing from the active version,
(3) Compute code returns backend-not-found errors or misroutes requests, (4) You're
surprised to see your draft version number "skipped over" in the version chain.
Root cause: `fastly compute publish` clones from the currently-active version, not from
the latest draft, so dashboard changes made in an un-activated draft get stranded.
author: Claude Code
version: 1.0.0
date: 2026-04-05
---
# `fastly compute publish` ignores non-active draft versions
## Problem
Fastly service versions are immutable. To change a service you clone the active version,
edit the clone (a draft), then activate the clone. Multiple tools create drafts:
- `fastly service backend create --autoclone` — creates a draft off the active version and
adds the backend
- `fastly service domain create --autoclone` — same, for domains
- Dashboard UI "Clone" button
- `fastly compute publish` — also creates a draft, uploads WASM, activates
If you mix these tools on the same service you get a surprising footgun: **each tool clones
from the currently-active version, independently, and each activates its own clone.** Draft
versions that were never activated are abandoned. Their edits are invisible to whatever the
next tool clones from.
Example sequence that bites:
```
t0 Active = v250
t1 $ fastly service backend create --version latest --autoclone \
--name cloud_run_transcoder --address ...
→ creates v251 (clone of v250) + adds backend
→ v251 is DRAFT, not active
→ "latest" in this context means "highest version number" (v251), not "active version"
t2 $ fastly compute publish --comment "ship fix"
→ creates v252 (clone of v250, NOT v251) + new WASM
→ stages and activates v253 (clone of v252) + activates
→ v251's backend change was never carried forward
→ active = v253, which does NOT contain cloud_run_transcoder
t3 Compute code at v253 calls send_async("cloud_run_transcoder")
→ backend name does not exist on v253
→ silent failure, fire-and-forget hides it
```
The naming is misleading: `--version latest` does not mean "the latest active version," it
means "the highest-numbered version," which can be a draft nobody activated. And `fastly
compute publish` never looks at your draft — it clones from whatever is currently active.
So your backend change is orphaned in an unreachable draft version, and the active version
has the new code but the old backend list.
## Context / Trigger Conditions
- Compute logs show `Backend X does not exist` or similar after a deploy that "worked"
- `send_async(BACKEND)` calls return errors that the code silently swallows (see skill
`fastly-compute-async-request-reliability`)
- `fastly service version list --service-id ID` shows a gap or out-of-order creation
timestamps — e.g. v251 created at 23:17, v252/v253 created at 23:27, v253 active, but
v252 was cloned from v250 not v251
- `fastly service backend list --version N` where N is active shows a DIFFERENT backend
set from `fastly service backend list --version (N-2)` where N-2 is the draft you
thought you were building on
- You added a dashboard resource "just before" running `fastly compute publish` and the
publish succeeded but the resource seems to be ignored
## Solution
### Detection
```bash
# Find all versions and which is active
fastly service version list --service-id YOUR_SERVICE_ID
# For each recent version, list backends (or whatever resource you added)
for v in 250 251 252 253 254; do
echo "=== v$v ==="
fastly service backend list --service-id YOUR_SERVICE_ID --version $v | grep MY_BACKEND_NAME
done
```
If the backend appears on a non-active draft (e.g. v251) but is absent from active (e.g.
v253), you have this bug.
### Fix: add the resource to the currently-active version via `--autoclone`
```bash
# Creates a new draft cloned from the active version, with the backend added.
# Activate the draft atomically afterward.
fastly service backend create --service-id YOUR_SERVICE_ID --version latest --autoclone \
--name cloud_run_transcoder \
--address divine-transcoder-149672065768.us-central1.run.app \
--port 443 --use-ssl \
--ssl-sni-hostname divine-transcoder-149672065768.us-central1.run.app \
--override-host divine-transcoder-149672065768.us-central1.run.app
# Confirm the draft has the backend
fastly service backend list --service-id YOUR_SERVICE_ID --version LATEST_DRAFT \
| grep cloud_run_transcoder
# Activate
fastly service version activate --service-id YOUR_SERVICE_ID --version LATEST_DRAFT
# Purge cache so any poisoned 404/502 responses drop
fastly purge --all --service-id YOUR_SERVICE_ID
```
Note: `--version latest` in the `backend create` command here is safe because after the
previous drifted `fastly compute publish`, the latest draft's parent IS the currently-active
version. You're cloning off the right base now.
### Prevention (choose one)
1. **Do all non-code changes through `fastly compute publish` first, then WASM changes.**
If you ran `fastly compute publish` without any dashboard/CLI changes queued, the active
version gets incremented by 2 (clone → activate) and there are no stranded drafts. Add
your backend after the publish via `--autoclone`, which then creates a fresh draft off
the new active version, and activate it.
2. **Always activate your draft before running `fastly compute publish`.** If you ran
`fastly service backend create --autoclone` and got v251, activate v251 before the
compute publish. Then compute publish will clone from v251 and carry the backend.
3. **Treat every draft version as an unshipped change.** Before any `fastly compute publish`,
run `fastly service version list --service-id ID` and verify no drafts exist that you
intended to ship. If there are drafts you don't want, explicitly abandon them; if there
are drafts you do want, activate them first.
4. **Use `--verbose` on `fastly compute publish`.** The verbose output shows which version
number it cloned from. If that number is older than your last draft, you know you've
drifted.
## Verification
After the fix, confirm:
```bash
# Active version has the backend
fastly service backend list --service-id YOUR_SERVICE_ID --version $(fastly service version list --service-id YOUR_SERVICE_ID | awk '$3=="true"{print $1}') | grep MY_BACKEND_NAME
# End-to-end: hit a Compute endpoint that exercises the backend and check logs
# for successful routing (no "backend does not exist" errors)
fastly log tail --service-id YOUR_SERVICE_ID | grep -iE "backend|MY_BACKEND"
```
For the Divine Blossom example (2026-04-05), the symptom was that PR #59's fix to route
transcoder triggers via a new `TRANSCODER_BACKEND = "cloud_run_transcoder"` constant was
deployed in version 253 but the backend itself was stranded in v251. The compute code was
silently 404-ing on every `send_async` to the transcoder. Fix was `fastly service backend
create --version latest --autoclone` → new v254 with both the WASM and the backend →
activate v254 → purge.
## Notes
- The same issue applies to *any* resource you can add with `--autoclone`: backends,
domains, ACLs, dictionaries, edge dictionaries, header rules, VCL snippets (on VCL
services), logging endpoints. Anything that creates a draft version is at risk.
- The `fastly compute publish` command has no `--base-version` flag to explicitly say "clone
from this version." It always clones from active.
- VCL services that mix `fastly vcl snippet create --autoclone` + `fastly vcl custom update`
can hit the same trap.
- If you have multiple people making changes concurrently, the risk multiplies: one person's
draft can be invalidated by another person's publish without either of them noticing.
- The Fastly CLI does not warn about stranded drafts. They don't expire automatically
(AFAIK); they just become zombie versions.
- Check `fastly service version list --service-id ID` output carefully — the "active"
column tells you which version is live; everything else is a draft or a previous active.
Timestamps can be misleading because draft versions carry the timestamp of the `fastly
service version clone` call, not of the content change.
## References
- `fastly compute publish` source behavior documented in the Fastly CLI repo — see the
`publish` subcommand implementation for the clone-active-and-activate flow
- Related skill: `fastly-compute-async-request-reliability` — covers how silently-failing
`send_async` hides this exact bug when the backend goes missing
- Related skill: `fastly-compute-backend-production-setup` — covers the "backend exists
locally but not in production" sibling bug
No comments yet. Be the first to comment!