# Architecture Overview
Understanding the architecture and design of cdk8s-plone deployments.
## Overview
cdk8s-plone provides CDK8S constructs for deploying Plone CMS on Kubernetes. The library handles all Kubernetes resources needed for a production-grade Plone deployment.
## Key Features
### Deployment Variants
cdk8s-plone supports two deployment variants:
**Volto (Modern)**
- React-based frontend (Volto)
- REST API backend (Plone)
- Separate services for frontend and backend
- Modern user experience
- Headless CMS architecture
**Classic UI (Traditional)**
- Server-side rendered Plone
- Single integrated service
- Traditional Plone experience
- Simpler deployment model
### High Availability
**Replica Management**
- Configurable number of replicas for backend and frontend
- Default: 2 replicas for each component
- Supports horizontal scaling
**Pod Disruption Budgets**
- Ensures minimum availability during cluster operations
- Configurable `minAvailable` and `maxUnavailable` thresholds
- Protects against voluntary disruptions (node drains, updates)
**Health Probes**
- Readiness probes: Traffic routing only to healthy pods
- Liveness probes: Automatic restart of unhealthy pods
- Configurable delays, timeouts, and thresholds
### HTTP Caching Layer
**Varnish Integration**
- Uses [kube-httpcache](https://github.com/mittwald/kube-httpcache) Helm chart
- Cluster-wide cache invalidation
- HTTP/2 support
- Configurable VCL
- Prometheus metrics export
**Benefits**
- Reduced backend load
- Improved response times
- Better scalability
- Automatic cache invalidation on content changes
### Caching Options
cdk8s-plone supports two HTTP caching approaches:
**PloneHttpcache (mittwald/kube-httpcache)**
- Self-contained: deploys Varnish via Helm chart, no operator needed
- Full VCL template with Go template variable injection
- Prometheus exporter sidecar for metrics
**PloneVinylCache (cloud-vinyl operator)**
- Operator-managed: creates a VinylCache custom resource
- Structured VCL generation with snippet injection hooks
- Built-in cache invalidation proxy (PURGE, BAN, xkey)
- Agent-based VCL delivery and Prometheus metrics
- Requires the [cloud-vinyl operator](https://github.com/bluedynamics/cloud-vinyl) in the cluster
Choose PloneHttpcache for standalone deployments without cloud-vinyl. Choose PloneVinylCache when the operator is available for centralized cache management.
### Multi-Language Support
The library is published in multiple languages:
**TypeScript/JavaScript**
- Native CDK8S experience
- Full TypeScript types
- Published to npm: `@bluedynamics/cdk8s-plone`
**Python**
- JSII-generated Python bindings
- Pythonic API
- Published to PyPI: `cdk8s-plone`
## Architecture Diagram
```mermaid
graph TB
subgraph "External Access"
Client[Client/Browser]
Ingress[Ingress Controller]
end
subgraph "HTTP Cache Layer (Optional)"
Varnish[Varnish Cache
kube-httpcache]
end
subgraph "Plone Frontend (Volto)"
FrontendSvc[Frontend Service]
Frontend1[Frontend Pod 1]
Frontend2[Frontend Pod 2]
end
subgraph "Plone Backend (API)"
BackendSvc[Backend Service]
Backend1[Backend Pod 1]
Backend2[Backend Pod 2]
Backend3[Backend Pod 3]
end
subgraph "Data Layer"
DB[(External Database
PostgreSQL/MySQL/Oracle
with RelStorage)]
end
Client --> Ingress
Ingress --> Varnish
Varnish -.cache miss.-> FrontendSvc
Varnish -.invalidation.-> BackendSvc
FrontendSvc --> Frontend1
FrontendSvc --> Frontend2
Frontend1 --> BackendSvc
Frontend2 --> BackendSvc
BackendSvc --> Backend1
BackendSvc --> Backend2
BackendSvc --> Backend3
Backend1 --> DB
Backend2 --> DB
Backend3 --> DB
```
## Component Responsibilities
### Backend
**Responsibilities:**
- Plone REST API
- Content management
- ZODB with RelStorage (external database)
- Search indexing
- Workflow engine
**Resources:**
- CPU: Compute-intensive operations (catalog queries, indexing)
- Memory: ZODB cache, Python processes
- Storage: Delegated to external database (PostgreSQL/MySQL/Oracle)
**Scaling:**
- Horizontal: Add replicas for read scalability with RelStorage
- Vertical: Increase resources for large catalogs
- External database handles storage and multi-writer scenarios
### Frontend (Volto)
**Responsibilities:**
- React single-page application
- Server-side rendering (SSR)
- API client
- User interface
**Resources:**
- CPU: SSR rendering, JavaScript execution
- Memory: Node.js processes, SSR caching
- Storage: Minimal (build artifacts only)
**Scaling:**
- Horizontal: Add replicas for traffic handling
- Vertical: Increase resources for SSR performance
- No shared storage needed (stateless)
### HTTP Cache (Varnish)
**Responsibilities:**
- HTTP caching
- Cache invalidation
- Request routing
- Load distribution
**Resources:**
- CPU: Request processing, cache lookup
- Memory: Cache storage
- Storage: Not required (in-memory cache)
**Scaling:**
- Horizontal: Add replicas for cache distribution
- Vertical: Increase memory for larger cache
## Kubernetes Resources Created
For a typical Volto deployment, cdk8s-plone creates:
**Backend:**
- Deployment (backend pods)
- Service (internal)
- PodDisruptionBudget (optional)
- ConfigMap (optional, for configuration)
**Frontend:**
- Deployment (frontend pods)
- Service (internal)
- PodDisruptionBudget (optional)
**HTTP Cache (optional):**
- StatefulSet (Varnish pods)
- Service (entry point)
- ConfigMap (VCL configuration)
- Secret (admin credentials)
- ServiceMonitor (optional, for Prometheus)
## Design Decisions
### CDK8S Constructs
**Why CDK8S?**
- Type-safe infrastructure as code
- Reusable components
- Familiar programming languages
- No templating required
- IDE support and IntelliSense
**Benefits:**
- Reduced boilerplate
- Better error detection
- Easier testing
- Composition over configuration
### Separate Frontend/Backend
**Volto Architecture:**
- Independent scaling of frontend and backend
- Frontend can be restarted without affecting backend
- Better resource utilization
- Clear separation of concerns
**When to use Classic UI:**
- Simpler deployment model
- Lower resource requirements
- Legacy integrations
- Specific add-on requirements
### Optional Varnish Layer
**Design Choice:**
- Varnish is optional, not mandatory
- Uses established Helm chart (kube-httpcache)
- Cluster-wide cache invalidation
- Production-tested solution
**Trade-offs:**
- Additional complexity
- More resources required
- Better performance at scale
- Reduced backend load
### Health Probes
**Readiness Probe:**
- Enabled by default for backend
- Prevents traffic to unready pods
- Fast startup detection
**Liveness Probe:**
- Disabled by default for backend (Plone is resilient)
- Recommended enabled for frontend (detect SSR hangs)
- Configurable thresholds
## Production Considerations
### Resource Planning
**Backend:**
- Plan for catalog size and query complexity
- ZODB cache size affects memory needs
- Indexing operations are CPU-intensive
**Frontend:**
- SSR requires CPU resources
- Memory for Node.js processes
- Scale based on traffic patterns
**Cache:**
- Memory size determines cache capacity
- Monitor hit rates and adjust sizing
### High Availability
**Recommendations:**
- Minimum 2 replicas per component
- Configure PodDisruptionBudgets
- Use node affinity for distribution
- Enable health probes
**Database:**
- External database required (PostgreSQL, MySQL, or Oracle)
- Uses RelStorage for ZODB persistence
- Enables true multi-writer deployments
- Better backup and recovery options
- MySQL derivatives (MariaDB, Percona) and Oracle are supported but untested
### Monitoring
**Metrics to Track:**
- Pod resource usage (CPU, memory)
- Request rates and latencies
- Cache hit rates
- Error rates
- Health probe failures
**Tools:**
- Prometheus for metrics collection
- Grafana for visualization
- Kubernetes events monitoring
## See Also
- [Plone Variants](plone-variants.md) - Detailed comparison of Volto vs Classic UI
- [Scaling Patterns](scaling-patterns.md) - Horizontal and vertical scaling strategies
- [Configuration Options](../reference/configuration-options.md) - Complete configuration reference
- [Quick Start](../tutorials/01-quick-start.md) - Getting started tutorial