Skip to content

Skew Protection

Skew Protection ensures version consistency between clients and servers during deployments. When a user begins a session on version N of an application, all subsequent requests within that session continue to be served by version N, even after version N+1 is deployed.

When a web application is redeployed, users who loaded the previous version’s frontend may send requests to the new version’s backend. This “version skew” causes failures when APIs, assets, or data schemas change between versions.

For example: a form field is renamed on both frontend and backend. Users who loaded the form before the deploy but submit after it will hit an error because the old field name is no longer recognized.

Standard Kubernetes rolling deployments replace pods gradually but don’t maintain session-to-version affinity. Kubernetes Services route to all healthy pods regardless of version.

ICC implements skew protection using the Kubernetes Gateway API for routing and session cookies for version pinning:

  1. Each application version runs as a separate, immutable K8s Deployment with its own Service
  2. ICC manages HTTPRoute resources that direct traffic to the correct version
  3. New visitors receive a __plt_dpl cookie pinning them to the current production version
  4. When a new version is deployed, existing users continue being routed to their pinned version via cookie matching
  5. Once the old version has no more traffic (or the grace period expires), ICC drains and cleans up the old version

ICC Deployments panel showing Active and Draining versions

ICC detects new versions automatically. When a pod registers with ICC, it reads the pod’s Kubernetes labels:

  • app.kubernetes.io/name — identifies the application
  • plt.dev/version — identifies the version

If the version is new for that application, ICC records it and updates the routing rules.

Routing is handled entirely by the Kubernetes Gateway API — no custom gateway or reverse proxy is required. ICC creates and manages HTTPRoute resources with rules that:

  • Match cookies — requests with a __plt_dpl cookie matching a draining version are routed to that version’s Service
  • Match headers — API clients can use the x-deployment-id header instead of cookies
  • Default to production — requests with no cookie or header match are routed to the current production version and receive a Set-Cookie response

The __plt_dpl cookie is set on responses to new visitors via the Gateway API’s ResponseHeaderModifier. The cookie includes:

  • HttpOnly — no JavaScript access
  • Secure — HTTPS only
  • SameSite=Lax — preserves pinning for users arriving via external links
  • Max-Age — configurable (default: 12 hours)
  • Path — scoped to the application’s path prefix
  • Opt-in only. Skew protection is disabled by default. When disabled, ICC does not interact with the Gateway API at all and behaves exactly as it does today.
  • User-managed Deployments. Users create their own versioned K8s Deployments. ICC does not create Deployments — it detects versions and manages routing.
  • Standard Kubernetes APIs. Uses the Kubernetes Gateway API (HTTPRoute resources). Any conformant Gateway controller works.
  • Labels, not environment variables. ICC reads app.kubernetes.io/name and plt.dev/version from K8s pod labels. No special environment variables needed for skew protection.