Saleor Deployment
Before writing code
Fetch live docs:
- Web-search
site:docs.saleor.io deployment production setup for production deployment guide
- Fetch
https://github.com/saleor/saleor-platform for Docker Compose reference configuration
- Web-search
site:docs.saleor.io environment variables configuration for required environment variables
- Web-search
saleor Celery worker configuration production for Celery setup details
- Web-search
site:docs.saleor.io cloud for Saleor Cloud managed hosting options
Production Docker Setup
Saleor provides an official Dockerfile with a multi-stage build:
| Stage |
Purpose |
Base Image |
| build |
Install dependencies, compile assets |
python:3.12-slim |
| production |
Run the application |
python:3.12-slim |
Docker Compose Services
| Service |
Image |
Purpose |
Port |
| api |
saleor (custom build) |
GraphQL API server (Gunicorn) |
8000 |
| worker |
saleor (same image) |
Celery worker process |
N/A |
| db |
postgres:15-alpine |
PostgreSQL database |
5432 |
| redis |
redis:7-alpine |
Cache and Celery broker |
6379 |
| dashboard |
saleor-dashboard |
React admin UI |
9002 |
| storefront |
Custom Next.js |
Customer-facing storefront |
3000 |
Saleor Cloud (Managed Hosting)
| Feature |
Description |
| Managed API |
Fully managed Saleor backend, no server maintenance |
| Auto-scaling |
Scales based on traffic automatically |
| Managed database |
PostgreSQL with backups and replication |
| CDN |
Built-in CDN for media and static assets |
| Environments |
Staging and production environments per project |
| CLI integration |
Deploy and manage via saleor CLI |
Access via https://cloud.saleor.io/ — create projects, manage environments, and deploy Apps.
Environment Variables
Required Variables
| Variable |
Description |
Example |
DATABASE_URL |
PostgreSQL connection string |
postgres://user:pass@host:5432/saleor |
SECRET_KEY |
Django secret key (50+ chars) |
Random string |
ALLOWED_HOSTS |
Comma-separated hostnames |
api.example.com,localhost |
DEFAULT_FROM_EMAIL |
Sender email address |
noreply@example.com |
CELERY_BROKER_URL |
Redis URL for Celery |
redis://redis:6379/1 |
Optional Variables
| Variable |
Description |
Default |
DEBUG |
Django debug mode |
False |
ALLOWED_CLIENT_HOSTS |
Storefront origins for CORS |
localhost |
DEFAULT_CURRENCY |
Fallback currency code |
USD |
DEFAULT_COUNTRY |
Fallback country code |
US |
MAX_CHECKOUT_LINE_QUANTITY |
Max qty per checkout line |
50 |
JAEGER_AGENT_HOST |
OpenTelemetry/Jaeger host |
None |
SENTRY_DSN |
Sentry error tracking DSN |
None |
Celery Worker Configuration
Celery runs as a separate process using the same Saleor codebase:
| Setting |
Value |
Description |
| Broker |
Redis |
CELERY_BROKER_URL = redis://redis:6379/1 |
| Result backend |
Redis |
Optional, for task result storage |
| Concurrency |
--concurrency=4 |
Number of worker threads |
| Queues |
celery (default) |
Default task queue name |
| Beat |
Optional |
Periodic task scheduler |
Key Celery Tasks in Saleor
| Task |
Purpose |
| Webhook delivery |
Send async webhook payloads to Apps |
| Email sending |
Transactional emails (order confirmation, etc.) |
| Thumbnail generation |
Generate product image thumbnails |
| Search indexing |
Update search index entries |
| Export processing |
Handle CSV/XLSX data exports |
S3-Compatible Media Storage
| Variable |
Description |
Example |
AWS_MEDIA_BUCKET_NAME |
S3 bucket name |
saleor-media-prod |
AWS_MEDIA_CUSTOM_DOMAIN |
CDN domain for media |
media.example.com |
AWS_ACCESS_KEY_ID |
IAM access key |
IAM credential |
AWS_SECRET_ACCESS_KEY |
IAM secret key |
IAM credential |
AWS_S3_REGION_NAME |
S3 region |
us-east-1 |
AWS_S3_ENDPOINT_URL |
Custom S3 endpoint (for MinIO, GCS) |
https://s3.example.com |
- Works with any S3-compatible service (AWS S3, Google Cloud Storage, MinIO, DigitalOcean Spaces)
- Set a CDN in front of the bucket for performance
- Configure CORS on the bucket to allow Dashboard uploads
PostgreSQL Configuration
| Setting |
Recommendation |
| Version |
PostgreSQL 14 or 15 |
| Connection pooling |
Use PgBouncer in transaction mode |
| SSL |
Require SSL connections (sslmode=require in DATABASE_URL) |
| Backups |
Automated daily backups with point-in-time recovery |
| Extensions |
pg_trgm (required for search), btree_gin |
| Max connections |
Size for Gunicorn workers + Celery workers + buffer |
Redis Configuration
| Purpose |
Database |
Variable |
| Cache |
redis://redis:6379/0 |
CACHE_URL |
| Celery broker |
redis://redis:6379/1 |
CELERY_BROKER_URL |
- Use separate Redis databases (or instances) for cache and Celery
- Enable Redis persistence (RDB snapshots or AOF) for the Celery broker
Database Migrations
Run migrations during deployment before starting the new application version:
- Always run
python manage.py migrate --noinput before starting Gunicorn/Celery with new code
- Back up the database before applying migrations
- Review migration SQL with
python manage.py sqlmigrate <app> <migration>
- For zero-downtime: ensure migrations are backward-compatible with the running code
Scaling Strategies
Horizontal Scaling
| Component |
Strategy |
Notes |
| API (Gunicorn) |
Add replicas behind load balancer |
Stateless, scale freely |
| Celery workers |
Add worker processes/containers |
Scale based on queue depth |
| Database |
Read replicas for queries |
Write goes to primary |
| Redis |
Redis Cluster or managed Redis |
Separate cache from broker |
Vertical Scaling
| Component |
Tune |
| Gunicorn |
--workers (2 * CPU + 1), --threads per worker |
| Celery |
--concurrency based on task type (I/O vs CPU) |
| PostgreSQL |
shared_buffers, work_mem, effective_cache_size |
Monitoring and Logging
| Tool |
Purpose |
Integration |
| Sentry |
Error tracking |
SENTRY_DSN environment variable |
| OpenTelemetry |
Distributed tracing |
OTEL_EXPORTER_OTLP_ENDPOINT |
| Prometheus |
Metrics collection |
django-prometheus middleware |
| Health check |
Liveness and readiness probes |
/health/ endpoint |
Production Checklist
| Item |
Action |
DEBUG |
Set to False |
SECRET_KEY |
Strong random value, stored in env var |
ALLOWED_HOSTS |
Restrict to actual domain names |
| Database |
SSL enabled, connection pooling, backups configured |
| Media storage |
S3-compatible with CDN |
| Celery |
Running as separate process with monitoring |
| HTTPS |
SSL termination at load balancer or reverse proxy |
| Migrations |
Applied before deploying new code |
| Monitoring |
Sentry, metrics, and health checks enabled |
Best Practices
- Run Celery workers as a separate container or process, never in the API process
- Use connection pooling (PgBouncer) between Gunicorn/Celery and PostgreSQL
- Store all secrets in environment variables, never in source code or Docker images
- Use multi-stage Docker builds to minimize production image size
- Run database migrations in a separate init container or deployment step
- Configure health check endpoints for load balancer and orchestrator probes
- Use S3-compatible storage with a CDN for media files
- Monitor Celery queue depth to detect processing backlogs
- Set up automated database backups with tested restore procedures
Fetch the deployment documentation for current Docker setup, environment variables, and scaling recommendations before implementing.
1---2name: saleor-deploy3description: Deploy Saleor to production — Docker setup, Saleor Cloud, environment variables, Celery workers, S3 media storage, database management, and scaling. Use when deploying Saleor applications.4---56# Saleor Deployment78## Before writing code910**Fetch live docs**:111. Web-search `site:docs.saleor.io deployment production setup` for production deployment guide122. Fetch `https://github.com/saleor/saleor-platform` for Docker Compose reference configuration133. Web-search `site:docs.saleor.io environment variables configuration` for required environment variables144. Web-search `saleor Celery worker configuration production` for Celery setup details155. Web-search `site:docs.saleor.io cloud` for Saleor Cloud managed hosting options1617## Production Docker Setup1819Saleor provides an official Dockerfile with a multi-stage build:2021| Stage | Purpose | Base Image |22|-------|---------|------------|23| **build** | Install dependencies, compile assets | `python:3.12-slim` |24| **production** | Run the application | `python:3.12-slim` |2526### Docker Compose Services2728| Service | Image | Purpose | Port |29|---------|-------|---------|------|30| **api** | `saleor` (custom build) | GraphQL API server (Gunicorn) | 8000 |31| **worker** | `saleor` (same image) | Celery worker process | N/A |32| **db** | `postgres:15-alpine` | PostgreSQL database | 5432 |33| **redis** | `redis:7-alpine` | Cache and Celery broker | 6379 |34| **dashboard** | `saleor-dashboard` | React admin UI | 9002 |35| **storefront** | Custom Next.js | Customer-facing storefront | 3000 |3637## Saleor Cloud (Managed Hosting)3839| Feature | Description |40|---------|-------------|41| **Managed API** | Fully managed Saleor backend, no server maintenance |42| **Auto-scaling** | Scales based on traffic automatically |43| **Managed database** | PostgreSQL with backups and replication |44| **CDN** | Built-in CDN for media and static assets |45| **Environments** | Staging and production environments per project |46| **CLI integration** | Deploy and manage via `saleor` CLI |4748Access via `https://cloud.saleor.io/` — create projects, manage environments, and deploy Apps.4950## Environment Variables5152### Required Variables5354| Variable | Description | Example |55|----------|-------------|---------|56| `DATABASE_URL` | PostgreSQL connection string | `postgres://user:pass@host:5432/saleor` |57| `SECRET_KEY` | Django secret key (50+ chars) | Random string |58| `ALLOWED_HOSTS` | Comma-separated hostnames | `api.example.com,localhost` |59| `DEFAULT_FROM_EMAIL` | Sender email address | `noreply@example.com` |60| `CELERY_BROKER_URL` | Redis URL for Celery | `redis://redis:6379/1` |6162### Optional Variables6364| Variable | Description | Default |65|----------|-------------|---------|66| `DEBUG` | Django debug mode | `False` |67| `ALLOWED_CLIENT_HOSTS` | Storefront origins for CORS | `localhost` |68| `DEFAULT_CURRENCY` | Fallback currency code | `USD` |69| `DEFAULT_COUNTRY` | Fallback country code | `US` |70| `MAX_CHECKOUT_LINE_QUANTITY` | Max qty per checkout line | `50` |71| `JAEGER_AGENT_HOST` | OpenTelemetry/Jaeger host | None |72| `SENTRY_DSN` | Sentry error tracking DSN | None |7374## Celery Worker Configuration7576Celery runs as a separate process using the same Saleor codebase:7778| Setting | Value | Description |79|---------|-------|-------------|80| **Broker** | Redis | `CELERY_BROKER_URL = redis://redis:6379/1` |81| **Result backend** | Redis | Optional, for task result storage |82| **Concurrency** | `--concurrency=4` | Number of worker threads |83| **Queues** | `celery` (default) | Default task queue name |84| **Beat** | Optional | Periodic task scheduler |8586### Key Celery Tasks in Saleor8788| Task | Purpose |89|------|---------|90| Webhook delivery | Send async webhook payloads to Apps |91| Email sending | Transactional emails (order confirmation, etc.) |92| Thumbnail generation | Generate product image thumbnails |93| Search indexing | Update search index entries |94| Export processing | Handle CSV/XLSX data exports |9596## S3-Compatible Media Storage9798| Variable | Description | Example |99|----------|-------------|---------|100| `AWS_MEDIA_BUCKET_NAME` | S3 bucket name | `saleor-media-prod` |101| `AWS_MEDIA_CUSTOM_DOMAIN` | CDN domain for media | `media.example.com` |102| `AWS_ACCESS_KEY_ID` | IAM access key | IAM credential |103| `AWS_SECRET_ACCESS_KEY` | IAM secret key | IAM credential |104| `AWS_S3_REGION_NAME` | S3 region | `us-east-1` |105| `AWS_S3_ENDPOINT_URL` | Custom S3 endpoint (for MinIO, GCS) | `https://s3.example.com` |106107- Works with any S3-compatible service (AWS S3, Google Cloud Storage, MinIO, DigitalOcean Spaces)108- Set a CDN in front of the bucket for performance109- Configure CORS on the bucket to allow Dashboard uploads110111## PostgreSQL Configuration112113| Setting | Recommendation |114|---------|---------------|115| **Version** | PostgreSQL 14 or 15 |116| **Connection pooling** | Use PgBouncer in transaction mode |117| **SSL** | Require SSL connections (`sslmode=require` in DATABASE_URL) |118| **Backups** | Automated daily backups with point-in-time recovery |119| **Extensions** | `pg_trgm` (required for search), `btree_gin` |120| **Max connections** | Size for Gunicorn workers + Celery workers + buffer |121122## Redis Configuration123124| Purpose | Database | Variable |125|---------|----------|----------|126| **Cache** | `redis://redis:6379/0` | `CACHE_URL` |127| **Celery broker** | `redis://redis:6379/1` | `CELERY_BROKER_URL` |128129- Use separate Redis databases (or instances) for cache and Celery130- Enable Redis persistence (RDB snapshots or AOF) for the Celery broker131132## Database Migrations133134Run migrations during deployment before starting the new application version:135- Always run `python manage.py migrate --noinput` before starting Gunicorn/Celery with new code136- Back up the database before applying migrations137- Review migration SQL with `python manage.py sqlmigrate <app> <migration>`138- For zero-downtime: ensure migrations are backward-compatible with the running code139140## Scaling Strategies141142### Horizontal Scaling143144| Component | Strategy | Notes |145|-----------|----------|-------|146| **API (Gunicorn)** | Add replicas behind load balancer | Stateless, scale freely |147| **Celery workers** | Add worker processes/containers | Scale based on queue depth |148| **Database** | Read replicas for queries | Write goes to primary |149| **Redis** | Redis Cluster or managed Redis | Separate cache from broker |150151### Vertical Scaling152153| Component | Tune |154|-----------|------|155| **Gunicorn** | `--workers` (2 * CPU + 1), `--threads` per worker |156| **Celery** | `--concurrency` based on task type (I/O vs CPU) |157| **PostgreSQL** | `shared_buffers`, `work_mem`, `effective_cache_size` |158159## Monitoring and Logging160161| Tool | Purpose | Integration |162|------|---------|-------------|163| **Sentry** | Error tracking | `SENTRY_DSN` environment variable |164| **OpenTelemetry** | Distributed tracing | `OTEL_EXPORTER_OTLP_ENDPOINT` |165| **Prometheus** | Metrics collection | `django-prometheus` middleware |166| **Health check** | Liveness and readiness probes | `/health/` endpoint |167168## Production Checklist169170| Item | Action |171|------|--------|172| `DEBUG` | Set to `False` |173| `SECRET_KEY` | Strong random value, stored in env var |174| `ALLOWED_HOSTS` | Restrict to actual domain names |175| Database | SSL enabled, connection pooling, backups configured |176| Media storage | S3-compatible with CDN |177| Celery | Running as separate process with monitoring |178| HTTPS | SSL termination at load balancer or reverse proxy |179| Migrations | Applied before deploying new code |180| Monitoring | Sentry, metrics, and health checks enabled |181182## Best Practices183184- Run Celery workers as a separate container or process, never in the API process185- Use connection pooling (PgBouncer) between Gunicorn/Celery and PostgreSQL186- Store all secrets in environment variables, never in source code or Docker images187- Use multi-stage Docker builds to minimize production image size188- Run database migrations in a separate init container or deployment step189- Configure health check endpoints for load balancer and orchestrator probes190- Use S3-compatible storage with a CDN for media files191- Monitor Celery queue depth to detect processing backlogs192- Set up automated database backups with tested restore procedures193194Fetch the deployment documentation for current Docker setup, environment variables, and scaling recommendations before implementing.