spree-deployment
Deploy Spree to production — PostgreSQL + Redis + Sidekiq stack, Docker multi-arch images on GHCR, the `spree-starter` Dockerfile + Compose, Heroku/Render/Fly.io/AWS targets, env-var conventions, RAILS_MASTER_KEY, asset precompilation (Tailwind 4 + Propshaft), Action Cable, MeiliSearch indexing, S3 / ActiveStorage for media, log/observability setup, zero-downtime deploys, and migration strategy. Use when going from local dev to production, scaling Spree, or troubleshooting deploys.
Best use case
spree-deployment is best used when you need a repeatable AI agent workflow instead of a one-off prompt.
Deploy Spree to production — PostgreSQL + Redis + Sidekiq stack, Docker multi-arch images on GHCR, the `spree-starter` Dockerfile + Compose, Heroku/Render/Fly.io/AWS targets, env-var conventions, RAILS_MASTER_KEY, asset precompilation (Tailwind 4 + Propshaft), Action Cable, MeiliSearch indexing, S3 / ActiveStorage for media, log/observability setup, zero-downtime deploys, and migration strategy. Use when going from local dev to production, scaling Spree, or troubleshooting deploys.
Teams using spree-deployment should expect a more consistent output, faster repeated execution, less prompt rewriting.
When to use this skill
- You want a reusable workflow that can be run more than once with consistent structure.
When not to use this skill
- You only need a quick one-off answer and do not need a reusable workflow.
- You cannot install or maintain the underlying files, dependencies, or repository context.
Installation
Claude Code / Cursor / Codex
Manual Installation
- Download SKILL.md from GitHub
- Place it in
.claude/skills/spree-deployment/SKILL.mdinside your project - Restart your AI agent — it will auto-discover the skill
How spree-deployment Compares
| Feature / Agent | spree-deployment | Standard Approach |
|---|---|---|
| Platform Support | Not specified | Limited / Varies |
| Context Awareness | High | Baseline |
| Installation Complexity | Unknown | N/A |
Frequently Asked Questions
What does this skill do?
Deploy Spree to production — PostgreSQL + Redis + Sidekiq stack, Docker multi-arch images on GHCR, the `spree-starter` Dockerfile + Compose, Heroku/Render/Fly.io/AWS targets, env-var conventions, RAILS_MASTER_KEY, asset precompilation (Tailwind 4 + Propshaft), Action Cable, MeiliSearch indexing, S3 / ActiveStorage for media, log/observability setup, zero-downtime deploys, and migration strategy. Use when going from local dev to production, scaling Spree, or troubleshooting deploys.
Where can I find the source code?
You can find the source code on GitHub using the link provided at the top of the page.
SKILL.md Source
# Spree Deployment
## Before writing code
**Fetch live docs**:
1. Fetch https://spreecommerce.org/docs/developer/deployment/database for the database setup story.
2. Inspect the `spree-starter` `Dockerfile` and `docker-compose.yml` for the current production stack.
3. Check the v5.4 announcement for multi-arch GHCR images and Docker improvements.
4. For your target platform, fetch its own Spree / Rails deployment guide (Heroku Ruby buildpack, Render Rails template, Fly.io Rails recipe).
5. Verify Sidekiq + Redis versions against the Gemfile.lock.
## Conceptual Architecture
### The Production Stack
| Tier | Component |
|------|-----------|
| **Web** | Puma serving the Rails app (Spree API + admin) |
| **Worker** | Sidekiq processing background jobs |
| **DB** | PostgreSQL 14+ (recommended) or MySQL 8 |
| **Cache + Jobs** | Redis 7+ |
| **Search** | MeiliSearch (v5.4+) or Algolia or Postgres FTS |
| **Media** | S3-compatible (ActiveStorage) |
| **Email** | SMTP (SendGrid, Postmark, SES) |
| **CDN** | CloudFront, Cloudflare, or platform-native |
| **Front-end (headless)** | Vercel for Next.js storefront |
| **Observability** | Sentry, Datadog, New Relic, AppSignal |
### What Each Component Does
- **Puma** — serves HTTP. The default config in spree-starter is multi-worker, multi-thread.
- **Sidekiq** — webhook delivery, email sending, image processing, search indexing, CSV imports.
- **PostgreSQL** — primary data store. Use pg_search (built-in to v5+ for full-text search if MeiliSearch isn't used).
- **Redis** — Sidekiq queues, Rails cache, Action Cable broadcasts.
- **MeiliSearch** — faceted product search (v5.4+ default).
- **S3** — product images, asset uploads, CSV import/export files.
- **CDN** — static assets + (optionally) full HTML response caching for catalog pages.
### Docker on GHCR (v5.4+)
Spree publishes multi-arch (ARM + x86) Docker images to GitHub Container Registry:
```
ghcr.io/spree/spree:5.4.2
ghcr.io/spree/spree-starter:latest
ghcr.io/spree/storefront:5.4.2
```
(Verify the exact image tags against the GHCR releases.)
### `spree-starter` Dockerfile
The starter ships a production-ready Dockerfile with:
- Multi-stage build (builder → runner)
- Asset precompilation in build stage
- `bootsnap` precompile for faster boot
- Tini as PID 1
- Non-root user
### Environment Variables
| Var | Purpose |
|-----|---------|
| `DATABASE_URL` | `postgres://user:pass@host:5432/db` |
| `REDIS_URL` | `redis://host:6379/0` |
| `RAILS_ENV` | `production` |
| `RAILS_MASTER_KEY` | Decrypts `config/credentials.yml.enc` |
| `SECRET_KEY_BASE` | If not in credentials |
| `RAILS_LOG_TO_STDOUT` | `true` for containerized envs |
| `RAILS_SERVE_STATIC_FILES` | `true` if no CDN in front |
| `WEB_CONCURRENCY` | Puma worker count |
| `RAILS_MAX_THREADS` | Threads per Puma worker |
| `MEILISEARCH_HOST`, `MEILISEARCH_API_KEY` | Search backend |
| `AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY`, `AWS_BUCKET`, `AWS_REGION` | ActiveStorage S3 |
| `SMTP_*` | Email |
| `SENTRY_DSN` | Error tracking |
| `STRIPE_*`, `ADYEN_*`, `PAYPAL_*` | Payment gateways |
| `SPREE_API_URL` | (Storefront-side) backend URL |
| `NEXT_PUBLIC_SPREE_PUBLISHABLE_KEY` | (Storefront-side) publishable key |
### Asset Precompilation
Spree v5 uses **Propshaft** + **Tailwind CSS 4**. In Dockerfile:
```dockerfile
RUN bin/rails assets:precompile RAILS_ENV=production
```
For Tailwind, `tailwindcss-rails` watches files at runtime in dev; in production, precompile bakes the final CSS. If using esbuild, run `bin/rails javascript:build` too.
### Database Migrations on Deploy
Run before traffic flips:
```bash
bin/rails db:migrate
```
For zero-downtime:
1. **Backward-compatible migrations only** (no column drops; no NOT NULL without default)
2. Migrate → deploy new code → wait one release cycle → drop deprecated columns
### Sidekiq Configuration
```ruby
# config/initializers/sidekiq.rb
Sidekiq.configure_server do |config|
config.redis = { url: ENV['REDIS_URL'] }
end
Sidekiq.configure_client do |config|
config.redis = { url: ENV['REDIS_URL'] }
end
```
```yaml
# config/sidekiq.yml
:concurrency: 10
:queues:
- critical
- default
- webhooks
- mailers
- low
```
Webhook delivery uses Sidekiq — without it, webhooks don't fire.
### Action Cable
For real-time admin updates (e.g., live order list refresh), Action Cable runs on the same Puma process. Redis is the broadcast adapter.
### MeiliSearch Indexing
After deploy:
```bash
bin/rails spree:search:reindex
```
(Verify the rake task name.) Run on a worker, not the web tier — long-running.
### Background Job Queues to Watch
- **Webhook delivery** — usually low-volume but bursty on bulk operations
- **Mailers** — high volume; separate queue helps prioritize
- **Image processing** — `ActiveStorage::AnalyzeJob` etc.; can fall behind on bulk uploads
- **Search indexing** — bursty on bulk product imports
### Backup Strategy
- PostgreSQL daily snapshots + WAL archive (or managed service backup)
- Redis is **ephemeral** — Sidekiq jobs lost on Redis loss is acceptable; recreate via re-publishing events
- S3 bucket versioning + cross-region replication
- `config/credentials.yml.enc` backed up alongside `RAILS_MASTER_KEY` (keep separate)
## Implementation Guidance
### Deploying to Heroku
```bash
heroku create my-spree
heroku addons:create heroku-postgresql:standard-0
heroku addons:create heroku-redis:premium-0
heroku addons:create sendgrid:starter
heroku buildpacks:add heroku/ruby
heroku buildpacks:add heroku/nodejs # for asset compilation
heroku config:set RAILS_MASTER_KEY=$(cat config/master.key)
heroku config:set RAILS_LOG_TO_STDOUT=true
heroku config:set RAILS_SERVE_STATIC_FILES=true
git push heroku main
heroku run bin/rails db:migrate
heroku run bin/rails spree:install
```
Run Sidekiq on a worker dyno:
```bash
heroku ps:scale web=2 worker=1
```
Procfile:
```
web: bundle exec puma -C config/puma.rb
worker: bundle exec sidekiq -C config/sidekiq.yml
release: bin/rails db:migrate
```
### Deploying to Docker (production)
```bash
docker build -t spree:latest .
docker run -d --name spree-web \
-e DATABASE_URL=... \
-e REDIS_URL=... \
-e RAILS_MASTER_KEY=... \
-p 3000:3000 \
spree:latest
docker run -d --name spree-worker \
-e DATABASE_URL=... \
-e REDIS_URL=... \
-e RAILS_MASTER_KEY=... \
spree:latest bundle exec sidekiq
```
For Kubernetes, use separate Deployments for `web` and `worker`, plus a Job for `db:migrate` on each release.
### Deploying the Next.js Storefront
**Vercel**:
- Connect repo → set env vars → deploy
- Vercel auto-detects Next.js and configures build
**Docker / self-hosted**:
- Multi-stage Dockerfile (the storefront repo ships one)
- Deploy to Fly.io / Railway / Cloud Run
### Caching Strategy
| Layer | What to cache |
|-------|---------------|
| **CDN** | Static assets (`/assets/*`, `/packs/*`) |
| **Rails fragment cache** | Product cards on PLP (busted by `product.updated`) |
| **Rails low-level cache** | Computed totals, settings |
| **Database query cache** | Per-request (default Rails behavior) |
| **Sidekiq result cache** | Webhook delivery dedup |
### Zero-Downtime Deploys
1. **Pre-migrate**: only backward-compatible migrations
2. **Boot new pods/dynos** before terminating old
3. **Drain old workers** — let Sidekiq finish in-flight jobs (`SIGTSTP` then `SIGTERM`)
4. **Health check** — readiness probe on `/admin/login_check` or similar low-overhead path
5. **Post-deploy cleanup migrations** — run after the next release cycle removes references
### Monitoring Checklist
- **Puma queue depth** — saturation indicator
- **Sidekiq queue latency** — webhook deliveries falling behind = retries pile up
- **Database connections** — Spree apps consume aggressively; tune pool size
- **PostgreSQL slow queries** — Spree's polymorphic associations sometimes generate full table scans
- **Redis memory** — Sidekiq retries can pile up
- **Search index health** — drift between PG and MeiliSearch
- **Error rate per endpoint** — `/api/v3/*` separate from admin
### Common Pitfalls
- **`RAILS_MASTER_KEY` not set** — app crashes at boot with cryptic error.
- **Missing Redis** — Spree silently degrades (cache misses), but Sidekiq won't start.
- **Forgetting `RAILS_SERVE_STATIC_FILES=true` without a CDN** — 404s on assets.
- **Skipping `db:migrate` on release** — runtime errors.
- **Single Puma worker on multi-CPU host** — leaving 80% of CPU idle.
- **Sidekiq concurrency too high** — exhausts DB connection pool.
- **No backup verification** — backups exist but aren't testable.
- **Storefront deployed with backend on different version** — API contract mismatch; pin in lockstep.
- **MeiliSearch index out of sync after deploy** — reindex after every release.
- **Heroku slug too large** — exclude `tmp/`, `log/`, `node_modules/` from slug.
Always cross-reference your platform's current Rails 7+ guide and the `spree-starter` repo's deployment notes — both move with each Spree release.Related Skills
spree-upgrades
Upgrade a Spree application — version-to-version migration paths (v4 → v5 is a major rewrite; v5.x → v5.y are simpler), Gemfile pinning strategy, decorator brittleness across versions, deprecated gems to remove (`spree_auth_devise`, `deface`, `spree_backend`), API v2 → v3 migration via `spree_legacy_api_v2`, admin Bootstrap → Tailwind transition, the upgrade guide workflow, and rollback strategy. Use when planning a Spree upgrade or auditing technical debt blocking one.
spree-typescript-sdk
Build storefronts and integrations using `@spree/sdk` — the official TypeScript SDK for Spree's API v3 (v5.4+). Covers installation, the resource-builder pattern (`spree.products.list`, `spree.checkout.create`, etc.), Zod schema validation, server-only auth (httpOnly JWTs, never exposing API keys), error handling, typing customizations, and pinning SDK versions to backend Spree releases. Use when integrating Spree into a Next.js / Node.js / TypeScript project.
spree-testing
Test Spree applications and extensions with RSpec — `spree_dev_tools` gem (v5.2+) for factories and helpers, FactoryBot patterns (prefer `build` over `create`), Capybara feature specs, controller/request specs, testing decorators and subscribers, dummy app for extension testing, system specs for the Hotwire admin, and CI patterns. Use when writing Spree tests, setting up CI, or refactoring slow specs.
spree-shipping-fulfillment
Build and customize Spree's shipping and fulfillment — ShippingMethod, ShippingCategory, Zone/ZoneMember, ShippingRate, the Stock::Estimator service, StockLocation/StockItem/StockMovement, multi-shipment orders, ShippingCalculator classes (FlatRate, FlatPercentItemTotal, PerItem, FlexiRate), shipment state machine, returns (ReturnAuthorization → CustomerReturn → Reimbursement → Refund), and integrating carrier APIs (UPS, FedEx, ShipStation). Use when configuring shipping rules, building fulfillment integrations, or debugging shipping-rate calculations.
spree-setup
Bootstrap a new Spree project — `create-spree-app` CLI (v5.2+), `spree-starter` Rails backend, the Next.js storefront repo, `bin/rails g spree:install`, sample data, Docker Compose, and the PostgreSQL + Redis + Sidekiq prerequisites. Use when starting a new Spree project from scratch or onboarding an existing repo.
spree-security
Secure a Spree deployment — Rails credentials and env-var hygiene, Devise auth (Spree v5 ships it in-core; `spree_auth_devise` is archived), CanCanCan authorization rules, Doorkeeper OAuth2 scopes, Storefront publishable key vs admin API key, webhook HMAC verification, OWASP Top 10 for Rails (mass assignment, CSRF, SQL injection via Ransack, XSS, IDOR through prefixed IDs), PCI scope (Spree never touches raw cards thanks to gateway tokenization), and multi-store data isolation. Use when auditing a Spree app, hardening a deploy, or addressing a security incident.
spree-promotions
Build and customize Spree's promotions engine — Promotion + PromotionRule + PromotionAction + CouponCode + Adjustment, the bundled rules (FirstOrder/ItemTotal/Product/Taxon/User/OneUsePerUser/Country/CustomerGroup/etc.), bundled actions (CreateAdjustment/CreateItemAdjustments/FreeShipping/CreateLineItems), Calculator classes, coupon batches with CSV export, the v5.1+ advanced rule-based engine, and authoring custom rules/actions/calculators. Use when modeling promotions, building discount UIs, or extending the promotions engine.
spree-performance
Profile and optimize a Spree application — N+1 queries with bullet/scout, database indexing strategy for Spree's polymorphic associations, Rails fragment + Russian doll caching, ActiveStorage variant pre-generation, Sidekiq queue tuning, MeiliSearch vs Postgres FTS tradeoffs, Puma worker/thread sizing, CDN strategy for catalog pages, asset precompile time, and load testing. Use when Spree is slow, the database is hot, or you're preparing for a traffic spike (Black Friday, launch).
spree-payments
Integrate payment gateways with Spree — PaymentMethod model, the v5.4+ PaymentSession provider-agnostic checkout flow, Stripe via `spree_stripe` (Apple/Google Pay, Link, Connect for marketplaces), Adyen via `spree_adyen`, PayPal via `spree_paypal_checkout`, StoreCredit / GiftCard as payment methods, refunds, payment state machine, and authoring a custom gateway. Use when wiring a payment integration, handling webhooks from a gateway, or debugging payment-state issues.
spree-multi-store
Configure Spree for multi-store and multi-region commerce — one Rails install running many `Store` records, the v5.4+ `Market` model (currency + locale + payment methods + shipping per region), what's shared vs per-store (products+inventory+customers shared; orders+payments+themes per-store), the Marketplace module (Enterprise — vendors/commission/payouts via Stripe Connect), and the Multi-tenant SaaS model. Use when planning a multi-brand or multi-region Spree deployment.
spree-legacy-api-v2
Work with Spree's legacy v2 APIs — JSON:API-style Storefront API at `/api/v2/storefront/*` and Platform API at `/api/v2/platform/*`, Doorkeeper OAuth2 (password grant for storefront, client_credentials + admin scope for platform), the `spree_legacy_api_v2` gem (required in v5+ for backward compatibility), and migration patterns to API v3. Use when maintaining a v2 client during a migration window, integrating an older partner system, or deciding when to cut over to v3.
spree-i18n
Localize a Spree application — the `spree_i18n` gem with 60+ locale packs, the v5.4+ Translations Center for product/CMS content (CSV import/export), Rails i18n basics applied to Spree (translation files, locale switching, pluralization, interpolation), per-Market locale routing in the headless storefront, RTL languages, and translating extensions. Use when localizing a Spree store, adding a new locale, or building i18n-aware extensions.