Skip to content

Deploying Versioned Applications

This guide explains how to deploy versioned applications that ICC can manage with skew protection. Each application version runs as a separate, immutable Kubernetes Deployment with its own Service.

Every versioned Deployment must include two labels on the pod template:

LabelRequiredPurpose
app.kubernetes.io/nameYesApplication identity — must be the same across all versions
plt.dev/versionYesVersion identifier — must be unique per version

ICC detects these labels automatically when the pod registers. No environment variables are needed for skew protection.

LabelPurposeDefault
plt.dev/pathCustom path prefix for HTTPRoute rules/{appName}
plt.dev/hostnameHostname for HTTPRoute (e.g., myapp.example.com)Not set (no hostname matching)

Create a Deployment and Service for each version. The key requirements:

  • Same app.kubernetes.io/name label across all versions
  • Unique plt.dev/version label per version
  • Unique Deployment and Service names (we recommend {appName}-{version})
  • PLT_ICC_URL configured to connect to ICC
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp-v1.2.4
namespace: platformatic
labels:
app.kubernetes.io/name: myapp
plt.dev/version: "1.2.4"
spec:
replicas: 3
selector:
matchLabels:
app.kubernetes.io/name: myapp
plt.dev/version: "1.2.4"
template:
metadata:
labels:
app.kubernetes.io/name: myapp
plt.dev/version: "1.2.4"
platformatic.dev/monitor: prometheus
spec:
containers:
- name: watt
image: your-registry.com/myapp:1.2.4
ports:
- name: app
containerPort: 3042
protocol: TCP
- name: metrics
containerPort: 9090
protocol: TCP
env:
- name: PLT_ICC_URL
value: "http://icc.platformatic.svc.cluster.local"
- name: PLT_SERVER_HOSTNAME
value: "0.0.0.0"
---
apiVersion: v1
kind: Service
metadata:
name: myapp-v1.2.4
namespace: platformatic
spec:
selector:
app.kubernetes.io/name: myapp
plt.dev/version: "1.2.4"
ports:
- name: app
port: 3042
targetPort: 3042
- name: metrics
port: 9090
targetPort: 9090

To deploy a new version of your application:

  1. Build a new container image with the updated application code (e.g., myapp:1.2.5)
  2. Create a new Deployment and Service manifest with the same app.kubernetes.io/name but a new plt.dev/version
  3. Apply the manifest:
Terminal window
kubectl apply -f myapp-v1.2.5.yaml
  1. ICC handles the rest — when the pods start and register with ICC, the new version is detected and routing transitions automatically

ICC treats the newest version as the production version immediately upon detection. The previous version transitions to Draining and continues serving existing sessions.

By default, ICC creates HTTPRoute rules with a path prefix of /{appName} (derived from app.kubernetes.io/name). If your application uses a different path, set the plt.dev/path label:

metadata:
labels:
app.kubernetes.io/name: myapp
plt.dev/version: "1.2.4"
plt.dev/path: "/api/leads"

The path prefix scopes the routing rules to your application, which is important when multiple applications share the same Gateway.

For production setups with per-application domains, set the plt.dev/hostname label:

metadata:
labels:
app.kubernetes.io/name: myapp
plt.dev/version: "1.2.4"
plt.dev/hostname: "myapp.example.com"

When set, ICC adds a hostnames field to the HTTPRoute, restricting the routing rules to requests matching that hostname.

Browser-based clients use the __plt_dpl cookie for version pinning automatically. For API clients (server-to-server, CLI tools, etc.) that don’t support cookies, use the x-deployment-id header:

Terminal window
curl -H "x-deployment-id: v1.2.3-abc123" https://myapp.example.com/api/data

The deployment ID value is the same identifier used in the __plt_dpl cookie. You can obtain it from the Set-Cookie response header on any request to the application.

To rollback to a previous version, re-deploy it as a new Deployment with the same version label. If the version was previously expired, ICC re-registers it as active.

Terminal window
# Re-deploy version 1.2.3 (which was previously expired)
kubectl apply -f myapp-v1.2.3.yaml

ICC treats this as a new version detection — it becomes the active version and the current version transitions to Draining.

After deploying, verify that ICC detected the new version:

  1. ICC Dashboard — navigate to the Deployments page and check for the new version in the active versions panel
  2. Logs — check ICC logs for version detection messages
  3. HTTPRoute — verify the HTTPRoute was created/updated:
Terminal window
kubectl get httproute -n platformatic
kubectl describe httproute myapp -n platformatic