Function Versions and Aliases

Publish immutable versions of a function, route traffic through movable aliases like prod and staging, split traffic between two versions, and roll back instantly — without touching triggers or paying a cold start.

Publish a function as immutable versions, point named aliases like prod and staging at them, and roll back a bad deploy in seconds — without editing a single trigger and without a cold start.

A plain fission fn update changes the live function in place. Every trigger that names the function immediately serves the new code, and the only way back is another update. Starting with Fission v1.27.0, a function can also have versions and aliases:

  • A version (FunctionVersion, kubectl get fnver) is an immutable snapshot of the function’s spec and package content at publish time, named <function>-v<sequence> (for example orders-v3). It is never mutated after creation, only garbage collected once nothing references it.
  • An alias (FunctionAlias, kubectl get fnalias) is a movable, named pointer at one version — or at two versions during a weighted traffic split. Triggers reference the alias; moving the alias is how a rollout or a rollback happens.
flowchart LR
  api["/api route"]:::user --> prod["alias: prod"]:::fission
  beta["/beta route"]:::user --> staging["alias: staging"]:::fission
  prod --> v3["orders-v3"]:::pod
  staging --> v4["orders-v4"]:::pod

  classDef user fill:#ffffff,stroke:#94a3b8,color:#1f2a43
  classDef fission fill:#e8f0fe,stroke:#2d70de,color:#1f2a43
  classDef pod fill:#e6f7f1,stroke:#11a37f,color:#1f2a43,stroke-dasharray:5 3

This is fully backward compatible. A trigger that references a bare function name keeps meaning “the live function”, exactly as before. Nothing changes until you publish a version and point something at it.

Publish a version

fission fn publish snapshots the function’s current spec and package content as the next version:

$ fission fn update --name orders --code orders-v2.js
Function 'orders' updated

$ fission fn publish --name orders --description "checkout rounding fix"
created orders-v3
next: fission alias create --function orders --name <alias> --version orders-v3

The first line is machine-readable (created <name>); the next: breadcrumb suggests the usual follow-up — pointing an alias at the fresh version. Publishing is idempotent: if nothing runtime-affecting changed since the last publish, the existing newest version is returned instead of minting a duplicate:

$ fission fn publish --name orders
unchanged orders-v3
next: fission alias create --function orders --name <alias> --version orders-v3
FlagMeaning
--descriptionHuman-readable note recorded on the version.
--waitWait for the function’s package build to finish before publishing (see --timeout); without it, publishing against a still-building package fails fast.
-o namePrint only the version name, for scripting.
-o json / -o yamlPrint the full version object.

Versions can also be minted automatically on every runtime-affecting update — see automatic publishing.

List versions

$ fission fn versions --name orders
NAME      SEQUENCE DIGEST              PUBLISHED            ALIASED-BY AGE
orders-v1 1        sha256:1f8ac10f23c5 2026-07-10T09:14:02Z -          14d
orders-v2 2        sha256:60303ae22b99 2026-07-17T16:41:55Z -          7d
orders-v3 3        sha256:fd61a03af4f7 2026-07-24T08:03:11Z prod       2m

The DIGEST column pins the exact package content of each version. ALIASED-BY shows which aliases currently reference it — a - means the version is unreferenced and eligible for retention GC. The table truncates digests. -o wide prints digests in full. It adds an ENVDRIFT column showing whether the version predates the environment’s current generation (see environment updates and drift). It also adds the DESCRIPTION recorded at publish time. -o name prints one version name per line, for scripting; -o json / -o yaml print the full objects.

To read a version rather than list them, fission fn get --version prints the exact source snapshot the version froze:

$ fission fn get --name orders --version orders-v2
module.exports = async (context) => {
    // ...
}

Point an alias at a version

$ fission alias create --name prod --function orders --version orders-v3 --wait
function alias 'prod' created
function alias 'prod' resolved

$ fission alias list
NAME    FUNCTION VERSION   PACKAGE-DIGEST WEIGHT SECONDARY-VERSION RESOLVED-VERSION
prod    orders   orders-v3                <none>                   orders-v3
staging orders   orders-v4                <none>                   orders-v4

--wait blocks until the alias’s Resolved condition confirms the target — the same flag alias update takes, so a CI job can gate on either. Without it, creation returns immediately and resolution completes asynchronously.

fission alias get --name prod shows the same row, plus the alias’s status conditions. Once the alias has been repointed at least once, it also shows a HISTORY block listing its previous targets, most recent last:

$ fission alias get --name prod
NAME FUNCTION VERSION   PACKAGE-DIGEST WEIGHT SECONDARY-VERSION RESOLVED-VERSION
prod orders   orders-v4                <none>                   orders-v4

CONDITIONS:
TYPE     STATUS REASON     MESSAGE                                                 LASTTRANSITION
Resolved True   Resolved   resolved to FunctionVersion "orders-v4"                 8s
EnvDrift False  EnvCurrent environment default/node generation 5 matches version "orders-v4"'s recorded generation 5 8s

HISTORY:
VERSION   SWITCHED-AT
orders-v2 2d
orders-v3 8s

The last history entry is what a bare fission fn rollback returns to. alias get is therefore the fastest way to see where a rollback would land. fission alias delete --name prod removes the alias. An alias lives in the same namespace as its function, and one function can have any number of aliases.

Testing an alias or version

fission fn test takes --alias and --version, so you can smoke-test one alias or one pinned version directly. It needs no trigger, and no wait for the alias to see traffic:

$ fission fn test --name orders --alias prod
{"order":"ok"}

$ fission fn test --name orders --version orders-v3
{"order":"ok"}

--alias and --version are mutually exclusive. Each is checked against the function before the request is sent. A typo’d name fails immediately with a clear error, instead of an opaque router 404:

$ fission fn test --name orders --alias staging
Error: alias "staging" not found for function "orders": functionaliases.fission.io "staging" not found

--async works with either flag too. Fission enqueues the invocation against the resolved alias/version route. It stays pinned to that target even if the alias moves before the function actually runs.

Inspecting versions, aliases, and their pods

fission fn describe on a versioned function ends with a VERSIONING section: the versioning mode, the version count, and one row per alias. Its PODS table also gains a VERSION column, showing which version each specialized pod serves:

$ fission fn describe --name orders
...
PODS:
NAME                                        NAMESPACE READY STATUS  IP          EXECUTORTYPE MANAGED SERVED VERSION
poolmgr-node-default-8750-844bd45565-9tvrj  default   2/2   Running 10.244.0.77 poolmgr      false   true   orders-v4
poolmgr-node-default-8750-844bd45565-pg8rk  default   2/2   Running 10.244.0.78 poolmgr      false   true   orders-v3

VERSIONING:
Versioning: mode=auto retain=10
Versions:   4
NAME    TARGET    WEIGHT ENVDRIFT
prod    orders-v3 <none> False
staging orders-v4 <none> False

Add --version to describe one version instead of the function. This inspects the immutable snapshot: its digest, publish-time description, the environment generation it was published under, and which aliases reference it:

$ fission fn describe --name orders --version orders-v3
Name:                    orders-v3
Function:                orders
Sequence:                3
Digest:                  sha256:fd61a03af4f77d870fc21e05e7e80678095c92d808cfb3b5c279ee04c74aca13
Description:             checkout rounding fix
Published:               2026-07-24T08:03:11Z
Age:                     2d
Entrypoint:              <none>
Environment:             node
Env Observed Generation: 5
Env Runtime Image:       ghcr.io/fission/node-env
Env Drift:               current

ALIASED-BY:
NAME TARGET    WEIGHT ENVDRIFT
prod orders-v3 <none> False

The same per-target filtering works on fission fn pods and fission fn logs. --version narrows to pods serving one pinned version; --alias follows an alias to whatever it currently resolves to. During a weighted split or an incident, that is the difference between reading interleaved logs from two versions and reading exactly the one you care about:

$ fission fn pods --name orders --version orders-v3
NAME                                        NAMESPACE READY STATUS  IP          EXECUTORTYPE MANAGED SERVED VERSION
poolmgr-node-default-8750-844bd45565-pg8rk  default   2/2   Running 10.244.0.78 poolmgr      false   true   orders-v3

$ fission fn logs --name orders --alias prod
...

--version and --alias are mutually exclusive on both commands.

Route triggers through the alias

A trigger targets an alias through the optional alias field on its function reference. The router resolves the alias at request time, so repointing the alias redirects traffic without touching the trigger.

Create the route with --function-alias:

$ fission route create --name orders-api --url /api/orders --method POST \
    --function orders --function-alias prod
trigger 'orders-api' created

--function-alias requires exactly one --function and is mutually exclusive with --function-version and with weighted multi-function routing. The same flag works on fission route update, with one wrinkle. Pass --function again alongside it — route update does not infer the target function from the existing route.

For GitOps pipelines, the same field is settable declaratively — write the trigger with --spec and edit the generated file, or apply YAML directly:

apiVersion: fission.io/v1
kind: HTTPTrigger
metadata:
  name: orders-api
  namespace: default
spec:
  relativeurl: /api/orders
  methods:
    - POST
  functionref:
    type: name
    name: orders
    alias: prod

Different routes can target different aliases of the same function:

# /api/orders -> alias prod (stable), /beta/orders -> alias staging (next)
functionref:
  type: name
  name: orders
  alias: prod
---
functionref:
  type: name
  name: orders
  alias: staging

To pin a route permanently to one immutable snapshot instead, pass --function-version orders-v3 (or set functionref.version: orders-v3 in YAML). Unlike an alias, a version pin never moves. alias and version are mutually exclusive, and both are valid on every trigger kind that embeds a function reference (HTTP, message queue, timer, Kubernetes watch).

Deploy by moving the alias

A deploy becomes: publish, then repoint.

$ fission fn update --name orders --code orders-v3.js
function 'orders' updated

$ fission fn publish --name orders --wait
created orders-v4

$ fission alias update --name prod --version orders-v4 --wait
function alias 'prod' updated
function alias 'prod' resolved

--wait blocks until the alias’s Resolved condition reports the new target, so a CI job can gate the next step on the switch actually happening. You can also wait separately: fission alias wait --name prod --for condition=Resolved.

Weighted traffic splits

An alias can spread traffic across two versions — the primary gets --weight percent, the secondary gets the rest:

$ fission alias update --name prod --version orders-v3 --weight 90 --secondary-version orders-v4
function alias 'prod' updated

Now 90% of requests through prod run orders-v3 and 10% run orders-v4. Step --weight down as confidence grows, then finish with a full repoint:

$ fission alias update --name prod --version orders-v4 --clear-weight
function alias 'prod' updated

--weight requires --secondary-version, and --clear-weight drops the split (it wins if combined with other flags in the same call). To have Fission step the weight for you based on error rates, drive the split with a canary config over the alias.

Instant rollback

fission fn rollback repoints one alias back at a previous version — atomically, and without recycling any pods:

$ fission fn rollback --name orders --alias prod --wait
function alias 'prod' rolled back: orders-v4 -> orders-v3
function alias 'prod' resolved

Confirm the alias is actually serving the rolled-back target with the same --alias flag fn test uses for smoke-testing:

$ fission fn test --name orders --alias prod
{"order":"ok"}

By default the alias returns to its previous target, which Fission records in the alias’s history on every switch. Pass --to to pick any version explicitly:

$ fission fn rollback --name orders --alias prod --to orders-v1
function alias 'prod' rolled back: orders-v3 -> orders-v1

Three properties make this safe to reach for during an incident:

  • No cold start. A version that any alias references keeps at least one specialized pod warm, so the rollback target is already running when traffic arrives.
  • Full repoint. A rollback clears any weighted split, so a rollback issued mid-canary stops the split entirely rather than rolling back only the primary side.
  • Atomic. The alias flips in a single update; there is no window where triggers see a half-moved state.

Rolling back a GitOps-managed alias

If the alias is owned by a fission spec directory (deployed with fission spec apply), a bare rollback is refused:

$ fission fn rollback --name orders --alias prod
Error: function alias 'prod' is managed by `fission spec` (Git); the next spec apply will revert this rollback. Re-run with --detach to strip spec ownership, and update your Git repo: set spec.version: orders-v3 in the FunctionAlias manifest

The guard exists because the next fission spec apply would reconcile the alias back to whatever spec.version says in Git — silently undoing the rollback. You have two options:

  • Git-first (preferred): change spec.version in the FunctionAlias manifest in your repository and let the pipeline apply it.
  • Emergency: re-run with --detach, which strips the spec-ownership annotations in the same update as the repoint, so a later spec apply no longer reverts it. Update the manifest afterwards, then re-apply to re-adopt the alias.

Declarative aliases and digest pinning

Aliases are ordinary objects in a spec directory, so a Git repository can own them:

apiVersion: fission.io/v1
kind: FunctionAlias
metadata:
  name: prod
  namespace: default
spec:
  functionName: orders
  version: orders-v3

For pipelines that build content before versions exist, an alias can pin by package digest instead of by version name:

spec:
  functionName: orders
  packageDigest: sha256:fd61a03af4f77d870fc21e05e7e80678095c92d808cfb3b5c279ee04c74aca13

The same pin works imperatively with --package-digest, on either alias create or alias update:

$ fission alias create --name prod --function orders \
    --package-digest sha256:fd61a03af4f77d870fc21e05e7e80678095c92d808cfb3b5c279ee04c74aca13
function alias 'prod' created

The pipeline commits the content hash it built; Fission resolves the digest to the version that recorded it, asynchronously, once that version exists. Because resolution is eventually consistent, gate on it in CI:

$ fission alias wait --name prod --for condition=Resolved --timeout 120s

version and packageDigest are mutually exclusive — exactly one must be set. Promotion between environments is then just two aliases converging. Point staging at a new version and test through the staging route. Promote by repointing prod at the same version — the identical immutable snapshot, not a rebuild.

Versions themselves are deliberately not spec-managed: the cluster mints them, and Git references them by name or digest.