Strapi is a stateful Node app — host it accordingly
Strapi is a self-hosted headless CMS, and the most common hosting mistakes come from treating it like a stateless app. Strapi needs three things in production: a persistent Node server (it's not serverless-friendly for the admin panel), a real database (SQLite is fine for dev, but use Postgres/MySQL in prod), and durable storage for uploaded media (the local filesystem won't survive container restarts — use an upload provider). Get those right and Strapi runs happily for years.
What matters for Strapi
- Always-on Node server (no scale-to-zero for the running instance in production).
- Managed Postgres or MySQL — not SQLite.
- Object storage upload provider (S3-compatible) so media survives redeploys.
- Enough memory — the admin build and runtime want 1GB+ comfortably.
- Environment-based config for DB credentials and app keys.
The options
| Platform | Persistent Node | Managed DB | Object storage | Notes |
|---|---|---|---|---|
| Strapi Cloud | Yes | Included | Included | First-party, easiest |
| DigitalOcean App Platform | Yes | Managed DB add-on | Spaces | Popular pairing |
| Render / Railway | Yes | Postgres | BYO S3 | Easy deploys |
| AWS/GCP (ECS/Run + RDS) | Yes | RDS/Cloud SQL | S3/GCS | Full control |
| PandaStack | Yes (container) | Yes (auto-wired) | BYO S3 | DB injected |
Strapi Cloud
Strapi Cloud is the path of least resistance — first-party hosting with the database and storage handled. If you want zero infrastructure decisions, it's the obvious choice. The trade-off is less control and platform-specific pricing.
Self-hosting Strapi
Many teams self-host for cost or control. The recipe is the same everywhere: run the Node server persistently, point it at a managed Postgres/MySQL, and configure an S3-compatible upload provider.
Where PandaStack fits
PandaStack is a clean self-host target for Strapi: deploy it as a container, attach a managed Postgres or MySQL, and let PandaStack inject DATABASE_URL. Strapi reads database config from the environment, so wiring is minimal:
FROM node:22-slim
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
ENV PORT=1337
CMD ["npm", "start"]// config/database.js — read the injected URL
module.exports = ({ env }) => ({
connection: {
client: 'postgres',
connection: env('DATABASE_URL'),
},
});You get a managed Postgres (14.x/16.x) or MySQL (5.7/8.x) with scheduled and manual backups, live logs, custom domains, and automatic SSL. Compute tiers scale from Free up through memory-optimized m1/m2 — for Strapi, choose a tier with at least ~1GB RAM.
Two honest pieces of guidance:
- 1Do not run Strapi on free-tier scale-to-zero. The admin panel and content API need an always-on instance; run it warm on a paid tier.
- 2Use an S3-compatible upload provider for media. PandaStack runs your container, but uploaded files written to the container filesystem won't persist across redeploys — configure
@strapi/provider-upload-aws-s3(or a compatible provider) pointed at object storage.
If you want zero-config hosting, Strapi Cloud is easier. PandaStack is the better fit when you want self-hosted Strapi with a managed database auto-wired and the freedom to run other services (a frontend, cronjobs) on the same platform.
Decision guide
- Easiest, first-party → Strapi Cloud.
- Self-host with managed DB auto-wired → PandaStack (warm instance + S3 uploads).
- Full cloud control → ECS/Cloud Run + RDS + S3.
References
- Strapi deployment docs: https://docs.strapi.io/dev-docs/deployment
- Strapi database config: https://docs.strapi.io/dev-docs/configurations/database
- Strapi upload providers: https://docs.strapi.io/dev-docs/providers
- Strapi Cloud: https://strapi.io/cloud
- Knex (Strapi's query builder): https://knexjs.org/
---
Self-hosting Strapi? PandaStack runs the Node server warm and injects a managed Postgres or MySQL automatically — just add an S3 upload provider for media. Start at https://dashboard.pandastack.io