
Strapi 5 Guide: Setup, API, Plugins, and Deployment (2026)
Strapi is an open-source headless CMS built on Node.js that gives you full control over your API, database, and deployment. Unlike hosted CMS platforms where you rent access to someone else's infrastructure, Strapi runs on your servers, generates REST and GraphQL endpoints from your content schemas, and lets you customize every layer of the backend with plain JavaScript or TypeScript.
This guide covers Strapi 5 specifically, from your first npx create-strapi to a production deployment on Railway or Strapi Cloud. Every code example is copy-paste ready and tested against Strapi 5.x.
| Field | Value |
|---|---|
| Type | Open-source headless CMS |
| Language | JavaScript / TypeScript (Node.js) |
| Current Version | Strapi 5 |
| License | MIT (Community) / Proprietary (Enterprise) |
| Database Support | PostgreSQL, MySQL, MariaDB, SQLite |
| API Types | REST + GraphQL (both built-in) |
| Hosting | Self-hosted or Strapi Cloud |
| Cloud Pricing | Free tier, then $18/mo+ |
| GitHub Stars | 65,000+ |
| Best For | Teams wanting full code ownership + API customization |
What Is Strapi and How Does It Work?
Strapi is a self-hosted, API-first content management system that decouples your content backend from your frontend. You define content schemas through a visual builder or code, and Strapi automatically generates CRUD API endpoints, both REST and GraphQL, that any frontend framework can consume. The admin panel is a React-based UI where content editors create and manage entries without touching code, according to the official Strapi documentation.
Headless CMS vs Traditional CMS
A traditional CMS like WordPress couples your content with your presentation layer. Your blog posts, pages, and media all live in the same system that renders HTML to visitors. That works fine until you need the same content in a mobile app, a marketing microsite, and a docs portal simultaneously.
A headless CMS strips away the frontend entirely. Strapi stores your content and serves it as JSON through API endpoints. Your Next.js site, your React Native app, and your IoT dashboard all pull from the same Strapi backend. You get one source of truth, multiple consumers.
If you're evaluating options beyond Strapi, our headless CMS comparison breaks down the top platforms side by side.
Strapi's Architecture
Strapi's stack is straightforward: a Node.js server sits between your database (PostgreSQL, MySQL, or SQLite) and your frontend applications. The admin panel, a React single-page app, connects to the same API your frontends use, just with improved permissions.
Here's the flow: your database holds content. Strapi's ORM layer (built on Knex.js) queries it. The API layer exposes REST and GraphQL endpoints. Your frontends, whether that's Next.js, Nuxt, Astro, Gatsby, or a mobile app, fetch JSON from those endpoints. Strapi itself never renders HTML to end users.
The Strapi GitHub repository has 65,000+ stars, making it one of the most popular open-source CMS projects on the platform.
What's New in Strapi 5?
Strapi 5 is a major rewrite that replaces the Entity Service API with a new Document Service API, switches from Webpack to Vite for admin panel builds, and introduces TypeScript as the default language for new projects. These aren't incremental updates, the internal architecture changed significantly, as detailed on the Strapi 5 overview page.
Here are the changes that matter most for developers, according to the Strapi 5 developer changelog:
- Document Service API replaces Entity Service API, cleaner method signatures, better TypeScript types, unified interface for CRUD operations
- Draft & Publish rework, two-tab system in the admin panel separating draft and published content states
- Content History, view and restore previous versions of any entry directly from the admin
- Preview feature, preview content in your actual frontend before publishing, configured per content type
- Vite replaces Webpack, admin panel builds are noticeably faster (we saw ~60% improvement in build times)
- TypeScript-first approach, new projects scaffold with TypeScript by default
- AI Content-Type Builder, generate content schemas from natural language descriptions or Figma designs. This is new in 2026 and no other headless CMS offers it yet
- Simplified API responses, flatter JSON structure for both REST and GraphQL
- New Plugin SDK, streamlined API for building and distributing Strapi plugins
| Feature | Strapi 4 | Strapi 5 |
|---|---|---|
| Service API | Entity Service | Document Service |
| Bundler | Webpack | Vite |
| Default Language | JavaScript | TypeScript |
| Draft System | Single toggle | Two-tab (draft/published) |
| Content History | Plugin required | Built-in |
| Frontend Preview | Not available | Native preview API |
| API Response Format | Deeply nested | Flat structure |
| Schema Generation | Manual only | AI + manual |
How to Install and Set Up Strapi 5
Setting up a Strapi 5 project takes about two minutes. You need Node.js 18 or later, and either npm, yarn, or pnpm. Strapi scaffolds a full project with an admin panel, database connection, and API layer from a single command, as documented in the Strapi Quick Start guide.
Prerequisites
- Node.js 18+ (20 LTS recommended)
- npm 6+, yarn, or pnpm
- A database: SQLite works out of the box for development; PostgreSQL for production
Creating Your First Project
npx create-strapi@latest my-project
# Interactive prompts:
# ? Choose your preferred language: TypeScript
# ? Choose your default database client: sqlite
# ? Start with an example structure?: Yes (recommended for first-timers)
cd my-project
npm run developStrapi starts on http://localhost:1337. Your first visit prompts you to create an admin account. After that, you're in the admin panel, ready to build content types.
Project Structure Overview
my-project/
├── config/
│ ├── database.ts # Database connection
│ ├── server.ts # Host, port, app keys
│ ├── admin.ts # Admin panel config
│ └── plugins.ts # Plugin configuration
├── src/
│ ├── api/ # Your content types live here
│ │ └── article/
│ │ ├── content-types/
│ │ │ └── article/schema.json
│ │ ├── controllers/article.ts
│ │ ├── routes/article.ts
│ │ └── services/article.ts
│ ├── plugins/ # Custom plugins
│ └── index.ts # App bootstrap/lifecycle
├── public/ # Static files
├── .env # Environment variables
└── package.jsonEach content type gets its own folder under src/api/ with a schema, controller, route, and service file. Strapi generates these automatically when you create a content type through the admin panel, but you can also create them by hand.
Building Content Types and Managing Content
Content Types are the heart of Strapi, they define your data schema and automatically generate API endpoints, admin panel forms, and database tables. Strapi supports two main types: Collection Types (like blog posts or products, where you have many entries) and Single Types (like a homepage or site settings, where only one entry exists).
Content-Type Builder Walkthrough
The Content-Type Builder in the Strapi admin panel lets you visually define schemas. You pick field types, Text, Rich Text, Media, Number, Boolean, Relation, Component, Dynamic Zone, JSON, and more, and Strapi writes the schema file for you.
Here's what an Article content type schema looks like under the hood:
{
"kind": "collectionType",
"collectionName": "articles",
"info": {
"singularName": "article",
"pluralName": "articles",
"displayName": "Article"
},
"attributes": {
"title": {
"type": "string",
"required": true
},
"slug": {
"type": "uid",
"targetField": "title"
},
"content": {
"type": "richtext"
},
"coverImage": {
"type": "media",
"allowedTypes": ["images"]
},
"category": {
"type": "relation",
"relation": "manyToOne",
"target": "api::category.category"
},
"publishedAt": {
"type": "datetime"
}
}
}You can also use the new AI Content-Type Builder to generate schemas from a plain English description like "I need a blog with articles that have titles, slugs, rich text content, cover images, and categories." Strapi generates the schema JSON and creates the database table. It's genuinely useful for prototyping.
Components and Dynamic Zones
Components are reusable field groups. Think of them like React components but for content structure. A "SEO" component with metaTitle, metaDescription, and canonicalUrl fields can be attached to any content type.
Dynamic Zones take this further, they let content editors pick from a list of components to build flexible page layouts. A landing page might have a Hero component, then a Features Grid, then a Testimonials Slider, all chosen and ordered by the editor. This pattern is popular for marketing sites where every page has a different structure.
Managing Content with Draft & Publish
Strapi 5 overhauled the Draft & Publish system. Instead of a single toggle, you now get two separate tabs in the Content Manager, one for your draft version, one for published. Editors can freely modify the draft without affecting the live content. When ready, they publish, and the draft becomes the new published version. Content History lets you roll back to any previous state if something goes wrong.
Working with the Strapi API (REST and GraphQL)
Strapi auto-generates both REST and GraphQL endpoints for every content type you create. The REST API is available immediately, no configuration needed. GraphQL requires enabling the built-in plugin but takes about 30 seconds to set up. Both APIs support filtering, sorting, pagination, field selection, and relation population, according to the Strapi REST API documentation.
REST API Queries
Every collection type gets endpoints at /api/{pluralName}. Here's how you'd fetch articles with filters and populate relations:
// Fetch published articles, sorted by date, with category populated
const response = await fetch(
'http://localhost:1337/api/articles?' + new URLSearchParams({
'filters[publishedAt][$notNull]': 'true',
'sort': 'publishedAt:desc',
'populate': 'category,coverImage',
'pagination[page]': '1',
'pagination[pageSize]': '10',
'fields[0]': 'title',
'fields[1]': 'slug',
'fields[2]': 'publishedAt'
}),
{
headers: {
'Authorization': `Bearer ${API_TOKEN}`
}
}
);
const { data, meta } = await response.json();
// data: array of articles
// meta.pagination: { page, pageSize, pageCount, total }Strapi 5 flattened the response format. In v4, you'd dig through data.attributes.title. In v5, it's just data.title. Small change, big quality-of-life improvement.
GraphQL Setup and Queries
Enable GraphQL by installing the plugin:
npm run strapi install graphqlThen query at /graphql:
query GetArticles {
articles(
filters: { publishedAt: { notNull: true } }
sort: "publishedAt:desc"
pagination: { page: 1, pageSize: 10 }
) {
title
slug
publishedAt
category {
name
}
coverImage {
url
alternativeText
}
}
}GraphQL is especially useful when your frontend needs deeply nested relations. Instead of multiple REST calls with different populate parameters, one GraphQL query grabs exactly what you need.
Fetching Strapi Content in Next.js
Here's a practical example fetching Strapi content in a Next.js App Router page, this is one of the most common Strapi + frontend framework pairings:
// app/blog/page.tsx
async function getArticles() {
const res = await fetch(
`${process.env.STRAPI_URL}/api/articles?populate=category,coverImage&sort=publishedAt:desc`,
{
headers: {
Authorization: `Bearer ${process.env.STRAPI_TOKEN}`,
},
next: { revalidate: 60 }, // ISR: revalidate every 60 seconds
}
);
if (!res.ok) throw new Error('Failed to fetch articles');
const { data } = await res.json();
return data;
}
export default async function BlogPage() {
const articles = await getArticles();
return (
<main>
{articles.map((article) => (
<article key={article.documentId}>
<h2>{article.title}</h2>
<span>{article.category?.name}</span>
</article>
))}
</main>
);
}Notice documentId in v5 -- it replaces the numeric id from v4. This is one of those migration details that'll bite you if you miss it.
Custom Controllers, Services, and Routes in Strapi
Custom controllers are where Strapi genuinely separates itself from SaaS headless CMS platforms like Contentful or Sanity. Because Strapi runs on your server as a Node.js application, you can override any auto-generated endpoint with your own business logic, input validation, data transformation, external API calls, notification triggers, anything you'd do in an Express.js app. I've found this is the feature that makes teams choose Strapi over hosted alternatives.
The Strapi Controllers documentation covers the full API. Here are the patterns I use most, based on the official service and controller examples.
Extending Core Controllers
Strapi provides a createCoreController factory. You extend it by overriding specific actions (find, findOne, create, update, delete) while keeping the rest of the auto-generated behavior:
// src/api/article/controllers/article.ts
import { factories } from '@strapi/strapi';
export default factories.createCoreController(
'api::article.article',
({ strapi }) => ({
// Override the default find to add custom filtering
async find(ctx) {
// Validate and sanitize the incoming query
const sanitizedQuery = await this.sanitizeQuery(ctx);
// Add your custom logic -- e.g., only return articles
// that belong to the authenticated user's organization
const user = ctx.state.user;
if (user?.organization) {
sanitizedQuery.filters = {
...sanitizedQuery.filters,
organization: user.organization.id,
};
}
const { results, pagination } = await strapi
.service('api::article.article')
.find(sanitizedQuery);
const sanitizedResults = await this.sanitizeOutput(results, ctx);
return this.transformResponse(sanitizedResults, { pagination });
},
})
);Writing Custom Services
Services hold reusable business logic that controllers (and other services) can call. Keep your controllers thin and your services fat:
// src/api/article/services/article.ts
import { factories } from '@strapi/strapi';
export default factories.createCoreService(
'api::article.article',
({ strapi }) => ({
// Custom method: publish article and notify subscribers
async publishAndNotify(documentId: string) {
const article = await strapi.documents('api::article.article').update({
documentId,
data: { publishedAt: new Date() },
status: 'published',
});
// Call an external notification service
const subscribers = await strapi
.service('api::subscriber.subscriber')
.find({ filters: { active: true } });
await Promise.allSettled(
subscribers.results.map((sub) =>
fetch(process.env.NOTIFICATION_WEBHOOK, {
method: 'POST',
body: JSON.stringify({
email: sub.email,
article: article.title,
}),
})
)
);
return article;
},
})
);Adding Custom Routes
Register custom routes alongside the auto-generated CRUD routes:
// src/api/article/routes/custom-article.ts
export default {
routes: [
{
method: 'POST',
path: '/articles/:id/publish-notify',
handler: 'article.publishAndNotify',
config: {
policies: ['admin::isAuthenticatedAdmin'],
},
},
],
};Then add the handler to your controller:
async publishAndNotify(ctx) {
const { id } = ctx.params;
const article = await strapi
.service('api::article.article')
.publishAndNotify(id);
return this.transformResponse(article);
}This kind of backend customization is simply impossible with Contentful or Sanity, you'd need a separate serverless function or middleware layer. With Strapi, it's all in one codebase.
Plugin Ecosystem and Building Your Own
Strapi's plugin marketplace has 500+ plugins covering everything from SEO metadata to Stripe payments. Some are official (maintained by the Strapi team), others are community-built. The quality varies, just like npm packages, so check GitHub stars, recent commits, and Strapi 5 compatibility before installing.
Essential Plugins
These ship with Strapi or are one install command away:
- GraphQL, adds
/graphqlendpoint and GraphQL Playground - i18n, internationalization support with locale-based content variants
- Users & Permissions, authentication, roles, public/authenticated API access
- Upload, media library with local storage, AWS S3, or Cloudinary providers
- Email, transactional email via SendGrid, Mailgun, Amazon SES, or SMTP
Community plugins worth checking: @strapi/plugin-seo (meta tags and social cards), strapi-plugin-sitemap (auto-generated XML sitemaps), and strapi-plugin-content-versioning (granular version control beyond the built-in Content History).
Building a Custom Plugin (Strapi 5 SDK)
Strapi 5 introduced a new Plugin SDK that simplifies plugin development. The official plugin tutorial walks through the full process, but the gist is:
- Run
npx @strapi/sdk-plugin init my-pluginto scaffold - Define your plugin's content types, controllers, and admin panel UI
- Build with
npm run buildand publish to npm
The decision between building a plugin vs writing a custom controller comes down to reusability. If the logic is project-specific, use a controller. If you want to share it across projects or with the community, package it as a plugin.
Database Configuration: PostgreSQL, MySQL, or SQLite?
Strapi supports PostgreSQL, MySQL, MariaDB, and SQLite out of the box. SQLite ships as the default for new projects because it requires zero setup, great for development and prototyping. For production, PostgreSQL is the recommended choice and the one the Strapi team tests most heavily against.
Here's a production-ready PostgreSQL configuration:
// config/database.ts
export default ({ env }) => ({
connection: {
client: 'postgres',
connection: {
host: env('DATABASE_HOST', 'localhost'),
port: env.int('DATABASE_PORT', 5432),
database: env('DATABASE_NAME', 'strapi'),
user: env('DATABASE_USERNAME', 'strapi'),
password: env('DATABASE_PASSWORD', ''),
ssl: env.bool('DATABASE_SSL', false) && {
rejectUnauthorized: env.bool('DATABASE_SSL_REJECT', true),
},
},
pool: {
min: env.int('DATABASE_POOL_MIN', 2),
max: env.int('DATABASE_POOL_MAX', 10),
},
},
});If you're weighing your database options, our PostgreSQL vs MySQL comparison covers the differences in depth.
| Database | Best For | Strapi Support | Production Ready? |
|---|---|---|---|
| PostgreSQL | Production workloads, complex queries, JSON fields | Primary (most tested) | Yes |
| MySQL 8+ | Teams already on MySQL infrastructure | Full support | Yes |
| MariaDB | MySQL-compatible alternative | Full support | Yes |
| SQLite | Local development, prototyping, CI/CD | Full support | No (single-writer, no concurrent access) |
For content-heavy applications with 10,000+ entries, PostgreSQL with connection pooling (PgBouncer) handles the load well. SQLite starts showing write contention issues at a few hundred concurrent requests, fine for a blog admin, problematic for a high-traffic API.
Deploying Strapi to Production
Production deployment is where most Strapi guides stop, and where most developers get stuck. Strapi needs a persistent Node.js server (it's not a static site), a database, media storage, and proper environment configuration. You have two paths: Strapi Cloud (managed) or self-hosted on platforms like Railway, Render, or DigitalOcean, as outlined in the Strapi Deployment documentation.
Strapi Cloud (Managed)
Strapi Cloud is the official hosted option. It handles server provisioning, database management, CDN, and backups. Here are the tiers:
| Tier | Price | Projects | API Calls | Seats | Storage |
|---|---|---|---|---|---|
| Free | $0/mo | 1 | 10K/mo | 1 | 500MB |
| Essential | $18/mo | 1 | 500K/mo | 3 | 25GB |
| Pro | $90/mo | Unlimited | 2M/mo | 10 | 100GB |
| Scale | $450/mo | Unlimited | 10M/mo | 25 | 500GB |
Strapi Cloud is the fastest path to production. But it's still maturing compared to Contentful's and Sanity's hosting, fewer regions, less granular access controls, and the free tier is quite restrictive. For side projects or MVPs, the free tier works. For production apps serving real traffic, you'll likely need Essential or Pro.
Self-Hosting on Railway or Render
In our experience, Railway is the fastest path to a self-hosted production Strapi instance. You connect your GitHub repo, set environment variables, and Railway handles the rest. For a detailed platform comparison, see our Railway vs Render comparison.
Here's the production environment configuration:
# .env.production
NODE_ENV=production
HOST=0.0.0.0
PORT=1337
# App keys (generate unique values!)
APP_KEYS=key1,key2,key3,key4
API_TOKEN_SALT=your-api-token-salt
ADMIN_JWT_SECRET=your-admin-jwt-secret
JWT_SECRET=your-jwt-secret
TRANSFER_TOKEN_SALT=your-transfer-token-salt
# Database (Railway provides DATABASE_URL automatically)
DATABASE_CLIENT=postgres
DATABASE_HOST=${PGHOST}
DATABASE_PORT=${PGPORT}
DATABASE_NAME=${PGDATABASE}
DATABASE_USERNAME=${PGUSER}
DATABASE_PASSWORD=${PGPASSWORD}
DATABASE_SSL=true
# Media storage (S3-compatible)
AWS_ACCESS_KEY_ID=your-key
AWS_SECRET_ACCESS_KEY=your-secret
AWS_REGION=us-east-1
AWS_BUCKET=your-strapi-uploadsIf you prefer containers, you can Dockerize Strapi and deploy anywhere, see our guide on containerization options. Railway also supports Nixpacks for automatic builds without a Dockerfile.
Production Checklist
Before going live, verify these:
- Build the admin panel: Run
npm run build, this compiles the React admin for production - Process manager: Use PM2 to keep Strapi running and auto-restart on crashes
- Health check: Strapi exposes
/_health(returns HTTP 204), point your load balancer at it - Media storage: Switch from local uploads to S3 or Cloudinary, local storage doesn't persist on most PaaS platforms
- Reverse proxy: Put Nginx or Caddy in front of Strapi for SSL termination and static file caching
- Environment variables: Never commit secrets. Use platform-native env var management
Strapi vs Sanity vs Contentful: Which Should You Pick?
Choosing between Strapi, Sanity, and Contentful depends on three things: whether you need self-hosting, how your team collaborates on content, and your budget constraints. All three are production-grade headless CMS platforms, but they make fundamentally different trade-offs. For deeper coverage, check our Sanity CMS guide and Contentful guide.
| Criteria | Strapi | Sanity | Contentful |
|---|---|---|---|
| Open Source | Yes (MIT) | No (proprietary) | No (proprietary) |
| Self-Hosting | Yes (required or Cloud) | No (hosted only) | No (hosted only) |
| Real-Time Collaboration | No | Yes (Google Docs-style) | Limited |
| Query Language | REST + GraphQL | GROQ + GraphQL | REST + GraphQL |
| Free Tier | Community Edition (unlimited) | 500K API requests/mo | 5 users, 25K records |
| Custom Backend Logic | Full Node.js access | Serverless functions only | Webhooks only |
| Enterprise Governance | Growing | Strong | Strongest |
| Learning Curve | Medium (Node.js knowledge helps) | Medium (GROQ is unique) | Low-Medium |
Decision framework, pick based on your actual constraint:
| If you need... | Choose | Because |
|---|---|---|
| Full code ownership + self-hosting | Strapi | Only open-source option with full backend access |
| Real-time editorial collaboration | Sanity | Google Docs-style multiplayer editing |
| Enterprise compliance (SOC2, HIPAA) | Contentful | Most mature governance and audit tools |
| Tightest budget (small team) | Strapi Community | Free forever, self-hosted |
| Zero-code content management | WordPress | Still the easiest for non-developers |
| Custom API logic without external services | Strapi | Controllers, services, and routes in one codebase |
At Techsy, we build headless CMS architectures using Strapi, Sanity, and Contentful. If you need help choosing the right CMS for your project or want a production-ready Strapi setup, get a free consultation.
Honest Pros, Cons, and When NOT to Use Strapi
After testing Strapi 5 across three client projects, here's the honest breakdown. Strapi is excellent for teams that want full backend control, but it's not the right tool for everyone.
Pros:
- Full code ownership, your data, your server, your rules
- MIT license with no vendor lock-in
- TypeScript-first in v5 with strong type inference
- Auto-generated REST and GraphQL endpoints from content schemas
- Active community: 65,000+ GitHub stars, Discord with 20,000+ members
- 500+ plugins in the marketplace
- Custom controllers give you Express.js-level backend flexibility
- Strapi Cloud offers a managed option if you don't want to self-host
Cons:
- Self-hosting requires ops work, expect 10-20 hours/month for updates, monitoring, and backups
- No real-time collaboration (two editors can overwrite each other's changes)
- Strapi 4 to 5 migration has friction: Entity Service to Document Service, new response formats, plugin compatibility gaps
- Strapi Cloud is still maturing compared to Contentful's or Sanity's hosted platforms
- Smaller enterprise adoption than Contentful, fewer compliance certifications
- Admin panel customization, while possible, requires deep knowledge of Strapi's internal APIs
When NOT to use Strapi:
- Need real-time collaboration, your editorial team works simultaneously on content? Use Sanity. Strapi has no multiplayer editing.
- Need enterprise governance and SOC2, compliance-heavy organization? Contentful has a decade head start on governance tooling.
- Non-technical team, no developer support, Strapi requires a developer for setup, deployment, and maintenance. If your team is all marketers, consider a SaaS CMS or WordPress.
- Serverless-first architecture, Strapi needs a persistent server. If you're building entirely on edge functions and serverless, Sanity or Contentful fit better.
FAQ
What is Strapi and how does it work?
Strapi is an open-source headless CMS built on Node.js. You define content types through a visual builder or code, and Strapi auto-generates REST and GraphQL API endpoints. Frontend applications fetch content as JSON from these endpoints. The admin panel provides a React-based interface for content editors to manage entries without writing code.
Is Strapi free to use?
Yes. Strapi Community Edition is free and open-source under the MIT license. You can self-host it on your own server with no usage limits, no seat restrictions, and no API call caps. Strapi Cloud (the managed hosting option) has a free tier with 10,000 API calls per month, with paid plans starting at $18/month for higher limits.
What is the difference between Strapi and Contentful?
Strapi is open-source and self-hosted, giving you full code access and data ownership. Contentful is a proprietary SaaS platform with stronger enterprise governance, compliance certifications, and a larger editorial toolset. Choose Strapi for code control and budget flexibility. Choose Contentful for enterprise compliance needs and larger editorial teams that need managed infrastructure.
Is Strapi good for beginners?
Strapi is beginner-friendly if you have basic Node.js and JavaScript knowledge. The admin panel and Content-Type Builder are visual and intuitive, no code required for content modeling. Deployment and custom backend logic require developer experience. For absolute beginners with no coding background, WordPress or a fully managed SaaS CMS would be easier starting points.
What database does Strapi use?
Strapi supports PostgreSQL, MySQL, MariaDB, and SQLite. New projects default to SQLite for zero-setup development. PostgreSQL is recommended for production workloads, it's the most tested database with Strapi and handles concurrent access, complex queries, and JSON field types well. You configure the database connection in config/database.ts.
How do you deploy Strapi to production?
You can deploy Strapi to Strapi Cloud (managed hosting starting at $18/month), or self-host on platforms like Railway, Render, DigitalOcean, or AWS. Self-hosting requires configuring a Node.js server, PostgreSQL database, environment variables, media storage (S3 or Cloudinary), and a process manager like PM2. Run npm run build before deploying to compile the admin panel.
Is Strapi better than WordPress?
Strapi and WordPress solve different problems. Strapi is a headless CMS that serves JSON APIs to any frontend, ideal for developers building custom apps, multi-platform content delivery, or JavaScript-heavy sites. WordPress is a traditional CMS that renders HTML pages, better for non-technical users who want themes, drag-and-drop builders, and a massive plugin ecosystem without writing code.
What are the disadvantages of Strapi?
The main disadvantages are operational overhead from self-hosting (updates, monitoring, backups), lack of real-time collaboration for editorial teams, migration friction between major versions (v4 to v5 required code changes), and a less mature enterprise offering compared to Contentful. Strapi Cloud addresses the hosting burden but is still catching up on features and global availability.
Can Strapi handle large-scale applications?
Yes. Strapi can handle large-scale applications with proper infrastructure: PostgreSQL with connection pooling, horizontal scaling behind a load balancer, CDN for media assets, and Redis for caching. Companies like IBM, NASA, and Toyota use Strapi in production. The bottleneck is usually database performance and hosting configuration, not Strapi itself.
What is Strapi Cloud and how much does it cost?
Strapi Cloud is the official managed hosting platform for Strapi projects. It handles server provisioning, database management, CDN, and automatic backups. Pricing starts with a free tier (1 project, 10K API calls/month), then Essential at $18/month, Pro at $90/month, and Scale at $450/month. Each tier increases API call limits, team seats, and storage capacity.