Loading learning content...
You've now explored Kubernetes' four primary workload types: Deployments, StatefulSets, DaemonSets, and Jobs/CronJobs. Each solves specific problems and provides different guarantees. But when faced with a real application, how do you choose?
The answer seems simple in theory—match your application's requirements to the workload type that provides those guarantees. In practice, however, applications often have nuanced requirements that aren't immediately obvious. Does your "stateless" API actually depend on local caching that affects behavior? Is your database truly requiring StatefulSet, or would a managed database service be better?
This page provides a systematic decision framework and explores the gray areas where the choice isn't obvious.
By the end of this page, you'll have a comprehensive decision framework for workload selection. You'll understand the key questions to ask, recognize common anti-patterns, and know how to handle applications that don't fit neatly into one category. You'll also learn when to use custom controllers or operators instead of built-in workload types.
The first step in workload selection is understanding your application's fundamental nature. Ask these questions in order:
Understanding the full capability matrix helps make informed decisions:
| Capability | Deployment | StatefulSet | DaemonSet | Job/CronJob |
|---|---|---|---|---|
| Primary use case | Stateless services | Databases, distributed systems | Node agents | Batch processing |
| Pod naming | Random (pod-abc123) | Ordinal (pod-0, pod-1) | Random | Random |
| Scaling model | replicas (0 to N) | replicas (0 to N) | One per node | completions/parallelism |
| Pod identity | Interchangeable | Unique, stable | Per-node | Independent |
| Storage per pod | Shared or none | Unique PVC per pod | hostPath or none | Shared or none |
| Startup order | Unordered (parallel) | Ordered (sequential) | Per-node (parallel) | Parallel or indexed |
| Shutdown order | Unordered | Reverse ordinal | Per-node | N/A (run to completion) |
| Update strategy | RollingUpdate, Recreate | RollingUpdate, OnDelete | RollingUpdate, OnDelete | N/A |
| Self-healing | Replace failed pods | Replace with same ID | Reschedule on node | Retry up to limit |
| HPA support | Yes | Yes | No (node-driven) | No |
| Service type | Regular Services | Headless + Regular | Headless or none | Usually none |
In most organizations, approximately 80% of workloads are Deployments (stateless services), 10% are Jobs/CronJobs (batch processing), and the remaining 10% split between StatefulSets (databases that haven't moved to managed services) and DaemonSets (logging/monitoring agents). If you find yourself using StatefulSets heavily, consider whether managed database services might be more appropriate.
Let's examine common application types and their ideal workload mappings:
Workload: Deployment
Most web applications and APIs are stateless by design:
Some web services have stateful characteristics: WebSocket servers with connection affinity, real-time collaboration tools with peer discovery, or servers with significant in-memory caching. Evaluate if these needs can be externalized (Redis, message queues) before choosing StatefulSet.
Not every application fits neatly into one category. Here's how to handle common gray areas:
When in doubt, start with the simpler option (usually Deployment). The operational overhead of StatefulSets and the complexity of managing state is significant. Many applications that "seem" stateful can be redesigned to be stateless by externalizing state to purpose-built systems (Redis, managed databases, object storage).
Workload misuse can lead to reliability issues, operational burden, and unexpected behavior. Avoid these common mistakes:
| Anti-Pattern | What Goes Wrong | Correct Approach |
|---|---|---|
| Deployment for databases | No stable identity, PVC reuse issues, split-brain during updates | Use StatefulSet with proper headless service or managed DB |
| StatefulSet for stateless apps | Unnecessary ordering slows scaling, complex PVC management | Use Deployment—simpler, faster scaling |
| DaemonSet for non-node workloads | Can't scale beyond node count, tied to cluster size | Use Deployment with appropriate replicas |
| CronJob for continuous processing | Missed runs, gaps in processing, concurrent run complexity | Use Deployment with queue-based worker |
| Job for indefinite processing | No completion = job never finishes, confusing status | Use Deployment or restructure with clear completion |
| Single-replica Deployment for leader | Brief dual-leader during rolling updates | Use leader election with Lease API |
Sometimes, the four built-in workload types aren't enough. Kubernetes' extensibility allows for custom workload types through Operators and Custom Controllers.
123456789101112131415161718192021222324252627282930313233
# Instead of manually configuring StatefulSets for Kafka...# Use Strimzi Kafka Operator's custom resource:apiVersion: kafka.strimzi.io/v1beta2kind: Kafkametadata: name: my-clusterspec: kafka: replicas: 3 listeners: - name: plain port: 9092 type: internal tls: false storage: type: persistent-claim size: 100Gi class: premium-ssd zookeeper: replicas: 3 storage: type: persistent-claim size: 10Gi entityOperator: topicOperator: {} userOperator: {} # The operator handles:# - StatefulSet creation and management# - Rolling updates with Kafka-aware ordering# - Cluster rebalancing during scale events# - TLS certificate management# - Topic and user management| Category | Operators | What They Manage |
|---|---|---|
| PostgreSQL | Zalando, CrunchyData, CloudNativePG | HA clusters, backups, failover, pooling |
| MySQL | Oracle MySQL, Percona, Vitess | Replication, scaling, backups |
| Kafka | Strimzi, Confluent | Brokers, topics, users, connectors |
| Redis | Redis Enterprise, Spotahome | Cluster mode, persistence, sentinel |
| Elasticsearch | ECK (Elastic) | Clusters, index management, snapshots |
| MongoDB | MongoDB Enterprise | Replica sets, sharding, backups |
| Prometheus | Prometheus Operator | Prometheus, Alertmanager, rules |
While operators simplify application management, they add a dependency. Evaluate: (1) Is the operator well-maintained and production-ready? (2) Do you understand what the operator does well enough to troubleshoot issues? (3) Is the operator's opinionated approach compatible with your needs? Sometimes, a well-configured StatefulSet is simpler than a poorly understood operator.
Use this checklist when deciding on a workload type for a new application:
1234567891011121314151617181920212223242526
FUNCTION chooseWorkloadType(application): IF application.needsManagedService(): RETURN "Use managed service (RDS, ElastiCache, etc.)" IF application.runsOnEveryNode(): RETURN "DaemonSet" IF application.runsToCompletion(): IF application.isScheduled(): RETURN "CronJob" ELSE: RETURN "Job" IF application.hasOperator() AND operator.isProduction(): RETURN "Use Operator (Custom Resource)" IF application.needsStableIdentity(): IF application.needsPersistentStoragePerPod(): RETURN "StatefulSet" IF application.needsStableDNS(): RETURN "StatefulSet" IF application.needsOrderedOperations(): RETURN "StatefulSet" RETURN "Deployment" // Default - simplest optionLet's consolidate the decision framework for workload selection:
| If You Need... | Use... |
|---|---|
| Horizontally scalable, interchangeable pods | Deployment |
| One pod per node, node-local access | DaemonSet |
| Run-to-completion tasks | Job |
| Scheduled periodic tasks | CronJob |
| Stable pod identity, ordered operations | StatefulSet |
| Complex stateful app with operational needs | Operator + CRD |
Congratulations! You've completed the Kubernetes Workloads module. You now understand all four workload types—Deployments, StatefulSets, DaemonSets, and Jobs/CronJobs—and have a decision framework for choosing the right one for any application. This knowledge forms a critical foundation for designing and operating production Kubernetes infrastructure.