Module 7 takes the agent you built in Module 6 and turns it into a production cloud service. You'll containerize the stack, orchestrate it on Kubernetes, automate delivery, and operate it with observability, security, and cost controls. The goal: a reliable Digital FTE that runs 24/7 for real users.
Prerequisites: Modules 4-6. You need a working agent service to deploy.
You understand the sidecar pattern and building blocks. Now it's time to deploy a real Dapr control plane and write code that uses it.
This lesson has two parts. First, you'll deploy Dapr on Docker Desktop Kubernetes using Helm—the same pattern you used for Kafka in earlier chapters. Second, you'll implement state management operations using the Python SDK, moving from simple save/get operations to handling concurrent updates with ETags.
By the end, you'll have Dapr running on your local Kubernetes cluster and a clear pattern for persisting state without writing any Redis-specific code.
Before deploying Dapr, verify your environment:
Output:
Output:
If either command fails, revisit earlier chapters to set up Docker Desktop Kubernetes and Helm.
Output:
Install Dapr 1.14 in the dapr-system namespace:
Output:
The --wait flag ensures Helm waits until all pods are ready before returning.
Check that all Dapr pods are running:
Output:
Each component has a specific role:
Dapr needs a backend for state storage. Deploy Redis using the Bitnami Helm chart:
Output:
Wait for Redis to be ready:
Output:
Dapr components tell the sidecar which backend to use. Create a file named statestore.yaml:
Apply the component:
Output:
Verify the component was created:
Output:
Your Dapr control plane is now running with a Redis state store configured. Any pod with Dapr annotations can now use the state API.
Now let's write Python code that uses Dapr's state management. You'll use the dapr-client SDK to save, retrieve, and delete state—without any Redis-specific code.
The DaprClient class provides a context manager for state operations:
Output:
Output:
Output:
When you need to save multiple items, bulk operations are more efficient:
Output:
When multiple processes might update the same state, you need concurrency control. Dapr uses ETags for optimistic concurrency—each state value has a version number, and updates only succeed if your version matches.
The problem: Two processes read the same todo, both modify it, both try to save. Without concurrency control, the last write wins and one update is lost.
The solution: Use the ETag returned with each read. If someone else modified the state since you read it, your ETag won't match and the save fails.
Output:
If another process updated the state between your read and write, you'd see:
In a real application, you'll integrate Dapr with FastAPI. Use the lifespan pattern for proper initialization:
This FastAPI application stores todos in Dapr state without any Redis-specific code. If you later switch to PostgreSQL or Cosmos DB, you change the component YAML—not your application code.
You might wonder: why add Dapr instead of using Redis directly?
For a single service using Redis forever, direct Redis is fine. For distributed systems where you might change backends or need consistent patterns across services, Dapr provides valuable abstraction.
You built a dapr-deployment skill in earlier lessons. Does it include both infrastructure deployment AND state management code patterns?
Ask yourself:
If you found gaps:
Deploy Dapr on Your Cluster
What you're learning: Dapr deployment follows the operator pattern you learned in earlier chapters (Strimzi). The control plane manages sidecar injection and security certificates—you declare what you want, Dapr figures out how to achieve it.
Create a FastAPI State Endpoint
What you're learning: The DaprClient context manager handles connection lifecycle. You don't manage Redis connections—you call save_state with a store name, and Dapr routes to the configured backend.
Explain ETag Concurrency
What you're learning: Concurrent state updates are a classic distributed systems problem. ETags provide optimistic concurrency—you assume no conflict and handle the rare case when one occurs. This is more performant than pessimistic locking for read-heavy workloads.
Safety note: When using Dapr state in production, never store secrets in plain text. Use the Secrets building block (later lessons) for credentials, and enable encryption at rest on your state store backend.