helm install to a green health probe takes under 25 minutes with this checklist.Before running a single kubectl command, your cluster must meet a baseline that prevents the most common production failures. Teams that skip this step report spending an average of 6 extra hours diagnosing issues that the checklist below catches in seconds.
startupProbe on all pods; versions below 1.16 silently ignore it.lookup functions introduced in 3.10; older Helm versions produce misleading template errors.Run the prerequisite validation script bundled with the chart: helm template flowsquad ./chart --dry-run --debug. If it exits 0, your values file is syntactically valid.
The Helm values file (values-prod.yaml) is the single source of truth for a production deployment. The chart exposes 47 values but only 12 are required for a functional cluster. The remainder control optional features like the LLM cost tracker, audit log retention, and horizontal pod autoscaler thresholds.
# values-prod.yaml — FlowSquad production Helm values replicaCount: 3 image: repository: ghcr.io/flowsquad/flowsquad tag: "2.4.1" pullPolicy: IfNotPresent ingress: enabled: true className: nginx host: flowsquad.internal.example.com tls: enabled: true secretName: flowsquad-tls database: host: pg-primary.db.svc.cluster.local port: 5432 name: flowsquad_prod sslMode: require poolSize: 20 maxOverflow: 10 vectordb: provider: pinecone indexName: flowsquad-prod environment: us-east1-gcp llm: defaultProvider: openai costTrackerEnabled: true auth: mfaRequired: true saml: enabled: false # enable for Keycloak SSO resources: requests: cpu: "500m" memory: "1Gi" limits: cpu: "2000m" memory: "4Gi" autoscaling: enabled: true minReplicas: 2 maxReplicas: 8 targetCPUUtilizationPercentage: 65
Store this file in your GitOps repository alongside secrets.yaml (sealed or SOPS-encrypted). Never commit raw secrets. The 3-replica default ensures zero-downtime rolling updates; with maxUnavailable: 1, at least 2 pods serve traffic during deploys.
PostgreSQL is FlowSquad's primary relational store for users, RBAC policies, epics, stories, tasks, audit logs, and LLM cost records. The schema is managed by Alembic migrations that run automatically in the init container before the app pod becomes ready.
The single most impactful tuning parameter is the connection pool. Load tests at 50 concurrent users show 3.2× more 500 errors when poolSize is left at the default of 5. Set it to at least 20 for teams over 10 engineers.
# Create the database and user kubectl exec -it pg-primary-0 -- psql -U postgres <<'EOF' CREATE DATABASE flowsquad_prod; CREATE USER flowsquad WITH PASSWORD 'use-a-vault-secret'; GRANT ALL PRIVILEGES ON DATABASE flowsquad_prod TO flowsquad; ALTER DATABASE flowsquad_prod OWNER TO flowsquad; EOF # Verify connectivity from inside the cluster kubectl run pg-check --image=postgres:16 --restart=Never --rm -it -- \ psql "postgresql://flowsquad:@pg-primary.db.svc.cluster.local:5432/flowsquad_prod?sslmode=require" \ -c "SELECT version();"
Enable audit logs on the PostgreSQL side too: set log_statement = 'ddl' and log_min_duration_statement = 1000. This feeds the SOC 2 CC6 evidence package that FlowSquad's built-in audit trail references.
Pinecone powers FlowSquad's AskProduct feature — semantic search over your codebase across all 11 supported languages. The index must be created before the app starts; FlowSquad validates index existence at boot and will refuse to start if dimensions mismatch.
# Python snippet — create Pinecone index before deploy import pinecone pinecone.init(api_key="YOUR_KEY", environment="us-east1-gcp") if "flowsquad-prod" not in pinecone.list_indexes(): pinecone.create_index( name="flowsquad-prod", dimension=1536, # OpenAI ada-002; use 768 for Ollama metric="cosine", pod_type="p2.x1", # production pod type replicas=2, shards=1 ) print("Index ready:", pinecone.describe_index("flowsquad-prod"))
For teams using ChromaDB instead (self-hosted), mount a 50 GB PersistentVolumeClaim at /data/chroma. The Helm chart creates this PVC automatically when vectordb.provider: chromadb and vectordb.persistence.enabled: true. With 300,000 embedded code chunks, ChromaDB uses approximately 12 GB on disk.
FlowSquad applies field-level encryption (Fernet/AES-128) to LLM API keys and database credentials at rest. However, these values still need to reach the pod at startup. Use Kubernetes Secrets (sealed with Sealed Secrets or SOPS) and mount them as environment variables — never bake them into the image.
# Required env vars — store in a K8s Secret named flowsquad-secrets FLOWSQUAD_DB_PASSWORD=<postgres-password> FLOWSQUAD_SECRET_KEY=<32-char-random-string> FLOWSQUAD_ENCRYPTION_KEY=<fernet-key-base64> FLOWSQUAD_OPENAI_API_KEY=<sk-...> FLOWSQUAD_PINECONE_API_KEY=<pinecone-key> FLOWSQUAD_PINECONE_ENVIRONMENT=us-east1-gcp # Create the Secret from a local .env file (gitignored) kubectl create secret generic flowsquad-secrets \ --from-env-file=.env.prod \ --namespace=flowsquad \ --dry-run=client -o yaml | kubectl apply -f -
Reference the secret in values-prod.yaml under envFrom so the Helm chart mounts it automatically. Rotate the Fernet key quarterly; FlowSquad's admin panel includes a key rotation wizard that re-encrypts all stored secrets without downtime.
Three probes are required. The startupProbe gives Alembic migrations up to 90 seconds to complete before liveness kicks in — without it, Kubernetes kills pods mid-migration. The livenessProbe restarts deadlocked workers. The readinessProbe gates traffic until the LLM provider connection pool is warm.
# Probe configuration (already in the chart, shown for reference) startupProbe: httpGet: path: /healthz/startup port: 8000 failureThreshold: 30 periodSeconds: 3 # 30 × 3s = 90s max startup window livenessProbe: httpGet: path: /healthz/live port: 8000 initialDelaySeconds: 5 periodSeconds: 10 failureThreshold: 3 readinessProbe: httpGet: path: /healthz/ready port: 8000 initialDelaySeconds: 10 periodSeconds: 5
For RBAC service accounts, FlowSquad needs a ServiceAccount with get/list/watch on ConfigMaps (for runtime config reloads) and get on Secrets (for the encryption key). No cluster-level permissions are needed — all access is namespace-scoped, satisfying least privilege requirements.
# Minimal RBAC for the FlowSquad service account
kubectl create serviceaccount flowsquad -n flowsquad
kubectl create role flowsquad-role \
--verb=get,list,watch --resource=configmaps \
--verb=get --resource=secrets \
-n flowsquad
kubectl create rolebinding flowsquad-binding \
--role=flowsquad-role \
--serviceaccount=flowsquad:flowsquad \
-n flowsquad
| # | Checklist Item | Command / Validation | Status |
|---|---|---|---|
| 1 | Kubernetes 1.27+ confirmed | kubectl version --short | ✔ Required |
| 2 | Helm 3.12+ installed | helm version | ✔ Required |
| 3 | Namespace created | kubectl create ns flowsquad | ✔ Required |
| 4 | PostgreSQL reachable & migrated | kubectl logs job/flowsquad-migrate | ✔ Required |
| 5 | Pinecone index dimension=1536 | Pinecone console | ✔ Required |
| 6 | Secrets created in namespace | kubectl get secret flowsquad-secrets | ✔ Required |
| 7 | TLS cert issued by cert-manager | kubectl get cert -n flowsquad | ✔ Required |
| 8 | RBAC ServiceAccount bound | kubectl auth can-i get secrets --as=system:serviceaccount:flowsquad:flowsquad | ✔ Required |
| 9 | HPA configured (min 2, max 8) | kubectl get hpa -n flowsquad | ✔ Required |
| 10 | All 3 pods Ready | kubectl get pods -n flowsquad | ✔ Required |
| 11 | Health endpoints return 200 | curl https://flowsquad.internal/healthz/ready | ✔ Required |
| 12 | 10-step setup wizard completed | Browser UI at /setup | ✔ Required |
| 13 | LLM cost tracker enabled | values-prod.yaml costTrackerEnabled: true | ⬡ Recommended |
| 14 | MFA enforced for all users | Admin panel → Auth settings | ⬡ Recommended |
| 15 | Audit log retention ≥ 90 days | Admin panel → Audit settings | ⬡ Recommended |
Yes. The chart is a standard Helm 3 chart with no pre/post hooks that require direct kubectl access. ArgoCD users should set server.helm.valuesFileSchemes: "secrets" if using the Helm Secrets plugin. Flux users can use HelmRelease with a valuesFrom reference to a sealed Kubernetes Secret for the sensitive values.
Alembic migrations are transactional. Each migration step runs in a transaction; if the connection drops, the transaction rolls back and the migration job exits with a non-zero code. Kubernetes re-runs the init container automatically. Alembic's version table ensures already-applied migrations are skipped on the retry. Average recovery time is under 45 seconds.
FlowSquad ships a migration CLI: flowsquad vectordb migrate --from chromadb --to pinecone --index flowsquad-prod. It re-indexes all existing embeddings in batches of 500. For a typical project with 200,000 chunks, migration takes approximately 18 minutes. Update the Helm values (vectordb.provider: pinecone) and do a rolling restart after the migration completes.
Benchmarks show each FlowSquad pod handles approximately 12 concurrent LLM requests before CPU saturation at the 2-vCPU limit. For 50 engineers with a peak concurrency factor of 0.3 (15 simultaneous sessions), 2 replicas are sufficient. Set HPA maxReplicas: 6 to handle burst without over-provisioning. Enable the LLM cost tracker to validate actual concurrency over the first 2 weeks.
Yes. The recommended pattern is one namespace per environment: flowsquad-staging and flowsquad-prod, each with its own Helm release, Secrets, and PostgreSQL database. RBAC policies and audit logs are completely isolated. The 10-step setup wizard generates environment-specific values.yaml files with a --env flag: flowsquad-setup --env staging.