Skip to content
STAGING — not production

Kubernetes StatefulSets for Trading Systems

StatefulSets vs Deployments, pod identity, PersistentVolumes, and graceful shutdown patterns for trading infrastructure.

Intermediate 20 min read Expert Version →

🎯 What You'll Learn

  • Understand when StatefulSets are required vs Deployments
  • Configure pod identity and stable network names
  • Implement graceful shutdown for trading workloads
  • Use PersistentVolumes for order state persistence

Why StatefulSets for Trading?

Trading systems are stateful:

  • Order management systems track open orders
  • Market makers maintain inventory positions
  • Matching engines preserve order book state

Deployments are for stateless apps. StatefulSets are for stateful apps.


StatefulSets vs Deployments

FeatureDeploymentStatefulSet
Pod namingRandom (app-xyz123)Ordered (app-0, app-1)
ScalingAll pods equalOrdered startup/shutdown
StorageShared or nonePer-pod PersistentVolumes
NetworkRandom IPsStable DNS names
Use caseStateless web appsDatabases, trading systems

When a Deployment pod restarts, it gets a new identity. Your order manager loses track of which orders belong to which pod. With StatefulSets, trading-0 is always trading-0 — even after restarts. This enables consistent order routing, per-pod state persistence, and predictable failover.


StatefulSet Definition

# trading-statefulset.yaml
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: order-manager
spec:
  serviceName: "order-manager"
  replicas: 3
  selector:
    matchLabels:
      app: order-manager
  template:
    metadata:
      labels:
        app: order-manager
    spec:
      terminationGracePeriodSeconds: 60  # Time to drain orders
      containers:
      - name: order-manager
        image: trading/order-manager:v1.2
        ports:
        - containerPort: 8080
        lifecycle:
          preStop:
            exec:
              command: ["/bin/sh", "-c", "kill -SIGTERM 1 && sleep 30"]
        volumeMounts:
        - name: order-state
          mountPath: /data/orders
  volumeClaimTemplates:
  - metadata:
      name: order-state
    spec:
      accessModes: ["ReadWriteOnce"]
      storageClassName: "fast-ssd"
      resources:
        requests:
          storage: 50Gi
```diff

This creates:
- `order-manager-0`, `order-manager-1`, `order-manager-2`
- Each pod gets its own 50Gi persistent volume
- 60s grace period for order draining

---

## Stable Network Identity

StatefulSets create DNS entries:

```bash
# Each pod gets a predictable DNS name
order-manager-0.order-manager.trading.svc.cluster.local
order-manager-1.order-manager.trading.svc.cluster.local
order-manager-2.order-manager.trading.svc.cluster.local
```text

Your order routing can use these stable names:

```python
# Route orders by symbol partition
def get_order_manager(symbol):
    partition = hash(symbol) % 3
    return f"order-manager-{partition}.order-manager:8080"
```diff

---

## Graceful Shutdown: Draining Orders

Trading pods can't just terminate. They must:
1. Stop accepting new orders
2. Complete pending orders
3. Persist state to disk
4. Terminate

```yaml
spec:
  terminationGracePeriodSeconds: 120  # 2 minutes to drain
  containers:
  - name: order-manager
    lifecycle:
      preStop:
        exec:
          command:
          - /bin/sh
          - -c
          - |
            # 1. Signal app to stop accepting new orders
            kill -SIGUSR1 1
            # 2. Wait for pending orders to complete
            /app/wait-for-drain.sh
            # 3. Persist final state
            /app/checkpoint-state.sh
```python

---

## Common Misconceptions

**Myth:** "I can use Deployments and just save state to Redis."
**Reality:** External state stores add latency and failure modes. For hot trading state (open orders, positions), local SSD with StatefulSet is faster and simpler.

**Myth:** "StatefulSets are slow to scale."
**Reality:** StatefulSets scale one pod at a time by default (ordered). For trading, this is a feature-you don't want 3 new order managers stealing positions simultaneously.

**Myth:** "PersistentVolumes survive node failures."
**Reality:** Depends on storage class. EBS-backed volumes survive node failures. Local NVMe does not. Choose based on your durability requirements.

---

## Headless Service for DNS

StatefulSets require a headless service:

```yaml
apiVersion: v1
kind: Service
metadata:
  name: order-manager
  labels:
    app: order-manager
spec:
  clusterIP: None  # Headless!
  ports:
  - port: 8080
    name: http
  selector:
    app: order-manager
```diff

`clusterIP: None` tells Kubernetes not to load-balance-instead, DNS returns individual pod IPs.

---

## AWS EKS Configuration

For trading on AWS:

```yaml
# Use io2 EBS for low-latency persistent storage
storageClassName: io2

# Node affinity for dedicated trading nodes
affinity:
  nodeAffinity:
    requiredDuringSchedulingIgnoredDuringExecution:
      nodeSelectorTerms:
      - matchExpressions:
        - key: node-type
          operator: In
          values:
          - trading

# Pod anti-affinity: spread across AZs
podAntiAffinity:
  requiredDuringSchedulingIgnoredDuringExecution:
  - labelSelector:
      matchLabels:
        app: order-manager
    topologyKey: topology.kubernetes.io/zone
```diff

---

## Practice Exercises

### Exercise 1: Create a StatefulSet
```bash
kubectl apply -f trading-statefulset.yaml
kubectl get pods -w  # Watch ordered startup
```text

### Exercise 2: Test Pod Identity
```bash
# Delete a pod, watch it come back with same name
kubectl delete pod order-manager-1
kubectl get pods -w
# order-manager-1 returns (not random name)
```text

## Exercise 3: Graceful Shutdown
```bash
# Scale down and watch drain
kubectl scale statefulset order-manager --replicas=2
# order-manager-2 gets preStop signal first

Key Takeaways

  1. StatefulSets = stable identity - Pod names survive restarts
  2. Ordered scaling - One at a time, predictable
  3. Per-pod storage - Each pod gets its own PersistentVolume
  4. Graceful shutdown is mandatory - Use preStop hooks

What’s Next?

Continue learning: Trading System Metrics

Expert version: Kubernetes StatefulSets: Why Trading Systems Need State

Want to go deeper?

Weekly infrastructure insights for engineers who build trading systems.

Free forever. Unsubscribe anytime.

You're in. Check your inbox.

Questions about this lesson? Working on related infrastructure?

Let's discuss