Back to Self-Hosted: When Enterprise Teams Trade SaaS CMS for Payload CMS

verified November 2026
Gleb Colei Frontend Developer
27 min

When your website runs on a SaaS platform like Contentful, Prismic, or Sanity, the vendor dictates the pricing, contracts, and infrastructure. The push to leave usually starts when engineering teams hit a hard ceiling: strict Contentful API limits, missing EU data storage, or the sudden realization of SaaS CMS vendor lock-in after a price hike or acquisition. (Though acquisitions happen in open-source, too—Payload joined Figma in 2025).

To regain control, many teams migrate to Payload CMS. It’s the kind of CMS your team runs itself. It’s open source, runs inside your Next.js app, and keeps content in your own Postgres database. The title talks about going back to self-hosted, so first, the data. There’s no way to measure that shift: none of the surveys we found count how many teams move from a SaaS CMS to one they run themselves. The only count of migrations, Storyblok’s State of CMS 2025 (over 1,300 CMS users surveyed), points the other way: fewer people moved to a new system over the past three years, “down an astonishing 31%”. The survey was run by Storyblok itself, a CMS vendor, and the methodology isn’t published. So this article looks at why some teams still move to Payload and what it costs them.

Below, we break down exactly what changes when you make the move, how to extract your data, and the true cost of ownership once you take the reins. Vendor data and pricing checked on November 9, 2026. Key points first.

Key takeaways

  • Standard export tools don’t get all the content out of a SaaS CMS. Contentful’s standard export leaves out version history and approval workflows, Prismic’s built-in export tool is deprecated, and Sanity keeps edit history for anywhere from 3 days on the Free plan to a year or a custom period on Enterprise. The vendor can end the contract too: under its Terms of Service (ToS), Contentful may do so with 30 days’ notice. Sanity lets you export through its standard tooling while you’re subscribed; after termination, it provides a copy only on written request, within 30 days. Vercel’s terms are similar: 30 days’ notice, or immediate termination if you exceed its limits.
  • In Payload, content sits in tables in your own Postgres database. You can query it directly, back it up and move it to another provider. In return, the team owns database schema changes (migrations).
  • With SaaS, the vendor decides where data lives: Contentful offers EU storage only on its top plan, Prismic has a single region in the US (us-east-1), and Sanity’s primary region is in Belgium (Google Cloud), with no documented way to choose another. With Payload you pick the region for the database, functions and media, but Vercel’s DPA allows processing outside the EU, the same kind of caveat Contentful gives for its EU region. The free open-source edition has no two-factor authentication (2FA) and no single sign-on (SSO).
  • Strict Contentful API limits (and similar quotas from Sanity and Prismic) go away, but hosting quotas stay: request size, paid bandwidth, file storage limits. Payload 3 has no general built-in rate limiting (there’s login lockout, and since 3.90.0 password reset requests are throttled), so the team sets up overload protection itself.
  • Custom fields, event handlers (hooks) and API endpoints are TypeScript in your own repository. Sanity lets you extend the Studio editor with your own code, but storage and server-side code stay on the vendor’s infrastructure.
  • Security updates become the team’s job as well. By November 2026, Payload has published 49 security advisories, and installing security release 3.90.0 on Postgres requires a database migration. With SaaS, the vendor ships server-side fixes on its end, so the numbers don’t compare directly.

What changes when the CMS becomes part of your app

Moving from Contentful, Prismic or Sanity to Payload changes four things: where the data lives and how you get it out, who decides on security and data location, which limits apply to the API, and how you extend the CMS. A separate section covers the overall cost: patches, updates, paid provider plans, editor features and ownership changes. We don’t compare other open-source CMSs here.

Self-hosted, in this article, means you own the code, the schema and the database. The servers can belong to someone else: the app can run on Vercel and the database on a managed Postgres service like Neon.

Contentful, Prismic and Sanity sell the CMS as a service under contract, and the data sits in their cloud. Sanity’s editor, Sanity Studio, is open source under MIT and can be deployed on any host, but the content store (Content Lake) exists only as the vendor’s service. So on contracts, data and limits, Sanity sits on the SaaS side of this comparison, and on extensibility it’s closer to Payload. We cover how Sanity works under the hood in ouropen-source Sanity alternative breakdown.Payloadis an MIT-licensed library that runs inside your Next.js app: the Payload admin and API ship in the same deployment as the site. That’s what makes theLocal APIpossible: your server code calls the CMS like a regular function, without an HTTP request. A frontend on a different stack can read content over REST or GraphQL, but then it can’t use the Local API.

The examples come from a project our team built for TalentWorldGroup(TWG). TWG is a Budapest-based, AI-driven business process outsourcing (BPO) company: it provides customer support, technical support and back-office operations across 100+ countries in 300+ languages, with more than 100 enterprise clients. Before the project, the company had three separate WordPress sites (a corporate site, one for clients and one for agents) plus a careers page, all on its own AWS infrastructure. Now it’s one platform on Payload and Next.js: Postgres on Neon, media in Vercel Blob, hosting on Vercel. TWG moved from WordPress, so its code shows what working with your own database and infrastructure looks like. We cover leaving a SaaS vendor in the Glimble section below.

Instead of a single SaaS vendor, a stack like this has several providers: Vercel (hosting and media), Neon (database) and Resend (email), each with its own contract, data processing agreement (DPA) and pricing.

Where your content lives and how to get it out

How to export content from Contentful, Prismic, and Sanity

What happens to your content when you leave is set out in the vendor’s contract and in the docs for its export tools. Section 8.2 of the Contentful Terms of Service lets the customer close the account at any time: “Customer may terminate Customer’s account at any time through the account management tools”. The vendor needs to give notice to do the same: “Contentful may terminate or suspend Customer’s account for any reason upon 30 days’ notice to Customer”, with no refund in that case. These ToS apply to self-service signups. If the company has a separate contract with Contentful, that contract applies instead.

Under section 2.1(e), backups are the customer’s job: “back up any data and information used in conjunction with the Subscription Services separately and at regular intervals”. EU customers are covered by the EU Data Act Addendum: when a customer notifies Contentful that it’s switching providers, it gets at least 30 days to retrieve its data, and that window starts after the notice period (up to two months) and the transition period (30 days). Under the Data Processing Addendum (DPA), Contentful deletes content within 35 days of a written request after the contract ends (section 10.1), so the export needs to be done before you send that request.

When you need to export content from Contentful, the standard CLI handles entries, assets, the content model, tags, locales, webhooks, and roles. However, it leaves critical data behind. It doesn’t export version history, scheduled actions, comments, tasks, approval workflows, releases (bundles of changes published together) or members. You have to pull those with your own code through the Content Management API (CMA), which allows 7 requests per second on Free and 10 on paid plans. Version history is usually lost in any CMS migration, and there’s no official way to bring it into Payload.

The Prismic ToS lets the vendor terminate if “we decide, in our sole discretion, to discontinue the product or service offering you are using” (section 4). After such a termination, Prismic may delete the data after 60 days (section 7.B). On keeping content safe, section 11 says: “You are encouraged to archive your content regularly and frequently”. Prismic deprecated its built-in Import/Export on April 30, 2024. The security page promises an export of all content with metadata (publication and modification dates) “through the tenant API endpoint”, but the docs don’t describe how to export version history or roles.

Section 4.4 of the Sanity ToS promises a copy of the data on written request within 30 days after termination, and explicitly limits retention: “Sanity is not obligated to maintain Subscriber Data for more than thirty (30) days following termination or expiration of the Subscription Term”. Section 9.1 of the Sanity DPA puts exports on the customer: “Subscriber is responsible for exporting Personal Data it wishes to retain before expiration or termination of the Agreement”.

The standard export includes documents with drafts and assets, and itself counts against the monthly API quota. Sanity keeps edit history for 3 days on Free, 90 on Growth and 365 or a custom period on Enterprise, and deletes older records. Backups that customers download and restore themselves exist only on some Enterprise plans and are off by default; Sanity’s internal copies, per its security page, are accessible only to vendor staff.

What owning the database gives you

In Payload, content is stored in tables in your database. For Postgres, Payload uses Drizzle, a TypeScript database library, and gives you direct access to it: “this adapter will expose the full power of Drizzle to you for use if you need it”. So everything Postgres can do is available: SQL queries for reporting, pg_dump, read replicas. You can move the database to another Postgres provider without a vendor export API. Leaving Payload itself for another CMS is still real work, though: you’ll have to unpack the data from the schema Payload built.

That schema isn’t easy to read by hand. By default, Payload’s Postgres adapter creates separate tables for blocks (reusable page sections, similar to slices in Prismic) and arrays in every collection that uses them, plus tables for locales, relationships and versions. That’s why a new field in three form blocks in the listing below had to be added to 21 tables. The blocksAsJSON option stores blocks in a JSON column; it doesn’t affect arrays.

The schema changes through migrations that live in the repository next to the code (schema migrations in the Payload docs). Some migrations move data as well as changing structure. Here’s a shortened migration from TWG that moved the form recipient address from site settings into its own collection:

// apps/payload/src/migrations/20261021_103321_form_recipients.ts (shortened)
export async function up({ db }: MigrateUpArgs): Promise<void> {
  await db.execute(sql`
    CREATE TABLE "form_recipients" ("id" serial PRIMARY KEY NOT NULL, "email" varchar NOT NULL /* … */);
    ALTER TABLE "page_blocks_lead_form" ADD COLUMN "recipient_id" integer;
    -- … same for the other 20 form block tables

    INSERT INTO "form_recipients" ("email") SELECT COALESCE(
      (SELECT NULLIF(trim("form_recipient_email"), '') FROM "site_settings" LIMIT 1),
      '…' -- default address
    );
    UPDATE "page_blocks_lead_form" SET "recipient_id" = (SELECT min("id") FROM "form_recipients");
    -- …

    ALTER TABLE "site_settings" DROP COLUMN "form_recipient_email";
    -- …
  `)
}
// down() moves the address back into site_settings

In Contentful, a similar data move is a script against the CMA; in Sanity, it goes through the built-in migration tooling (sanity migrations run), which sends changes to Content Lake. Adding a field in a SaaS CMS doesn’t need an SQL migration: it’s a change to the content model or the Studio schema. In Payload on Postgres, the same field means a migration, with the rollback written in down().

In dev mode, Payload syncs the schema automatically by default (push mode), and the docs warn: “do not mix ‘push’ and migrations with your local development database”. If a table was created outside a migration, through push in dev mode or drizzle-kit push, and you later generate a migration with the same table, its CREATE TABLE will fail on any database where the table already exists. If that’s a shared or production database, the deployment stops. If push has already run against a database in dev mode, Payload warns about it before migrate. But it doesn’t compare the database schema with your migrations, and it won’t notice a table created through drizzle-kit push or by hand.

Hosting lock-in and content migration

On TWG, the Neon integration with Vercel creates a separate database branch for the preview deployments of each git branch: a copy you can change without touching production. That’s a Neon feature; Payload has no mechanism of its own, so you’ll have to rebuild it if you switch providers. The same goes for the rest of the infrastructure: Blob storage, cron and Vercel functions. Payload runs anywhere Next.js runs, but moving off Vercel to your own Docker setup is a project of its own: Blob storage gets swapped for an S3-compatible store, cron for your own scheduler, and Vercel BotID, the platform’s bot protection service, has to be replaced with an alternative.

Infrastructure contracts have exit terms too. Section 19.1 of the Vercel ToS allows Vercel to terminate an account “at any time by providing thirty (30) days prior notice”, and immediately if you exceed its limits; after termination, content “may be permanently deleted”, with no export window. Neon’s contract is now with Databricks, “the parent company of Neon, LLC” (Neon terms). Under the Databricks agreement, either party can terminate with 30 days’ notice, and Databricks can suspend access without notice if it suspects a breach. Under its DPA, data is deleted within 30 days of a request after termination, again with no export window. Media in Vercel Blob has to be pulled out with your own script through the Blob SDK. The difference from a SaaS CMS is the exit format: while the account is active, you export the database with pg_dump in standard Postgres format rather than through a CMS export API.

Before launch, content gets moved over from the old CMS: models are mapped to Payload collections, rich text is converted, assets are transferred and URLs are preserved. Payload has no official migration tool for Contentful, Prismic or Sanity; the closest thing is a post with a video by a Payload partner. For what this looks like in practice, see our write-ups on an automated migration of 16,500 pages from Storyblok to Payload and a migration from Prismic.

Security and data location: who decides

Region and certifications at Contentful, Prismic and Sanity

With a SaaS CMS, the vendor sets the region and the security features. By default, Contentful stores data in AWS us-east-1 with a secondary region in us-west-2. EU data residency is available “on Premium plans only”, and even then the vendor writes: “Contentful cannot guarantee that data stored in the EU is only processed in and accessed from the EU”. Contentful’s docs call the top plan Premium, while the pricing page lists Free, Lite and Enterprise as the public plans. SSO, SCIM (automatic user provisioning and deprovisioning from a corporate directory) and custom roles are Enterprise-only there.

Prismic offers no choice of region. Its security page says: “Prismic services and customer data are hosted on Amazon Web Services (AWS) infrastructure in the us-east-1 region”. The certifications listed there belong to AWS and the payment provider Stripe; the page lists no SOC 2 report or ISO 27001 certification (independent security audit standards) of Prismic’s own. There’s no public DPA: “Prismic is in the process of making a DPA available online”, and for now it’s added only to a written Enterprise contract.

According to its subprocessor list, Sanity runs on Google Cloud with Belgium as the primary region and a US location as well. The security page mentions both a backend in a single EU region and storage in regions chosen for the customer, but the docs don’t describe how to choose a region or on which plan. Sanity has its own SOC 2 Type 2 report (Security criterion), and ISO 27001 is listed for Google Cloud. SAML SSO, custom roles and the audit log are Enterprise-only on the pricing page. Per the same subprocessor list, Sanity Functions run on AWS in the US and Germany.

With Payload, you pick the region and access control is code

With Payload, data location comes down to three decisions the team makes: the database region, the serverless function region and the media storage region. If you need EU residency, pick EU regions for all three. The infrastructure has caveats too, though: in its DPA, Vercel reserves the right to process data in the US “and anywhere else in the world”, and its security page states: “No data is stored permanently inside EU regions”. For strict data residency requirements, that’s the same kind of caveat as Contentful’s. Access control is defined with functions at the collection, field and document level. The rules live in the repository and go through code review with the rest of the code.

In Payload 3, the Local API skips access checks by default: “In the Local API, all Access Control is skipped by default” (access control docs). Server code that calls Payload directly sees everything until the developer passes overrideAccess: false along with the user. Payload 4 flips this default, but 4.0 is still in beta.

2FA and SSO

The open-source edition of Payload has neither 2FA nor SSO. SSO is listed among Payload Enterprise features, so at Contentful, Prismic, Sanity and Payload alike, SSO sits behind the top tier. 2FA isn’t on the Enterprise feature list. On TWG, admin login through the corporate identity provider is built in-house on OIDC (OpenID Connect, the standard for signing in with an external account). Custom authentication code is attack surface the team maintains, like any third-party plugin. TWG’s admin login has no 2FA either.

Contentful Prismic Sanity Payload (open source) + your hosting
Region choice US by default, EU only on Premium us-east-1 only Google Cloud, primary region Belgium; choice not documented you pick the database, function and media regions; Vercel reserves the right to process data outside the region
SSO Enterprise Enterprise Enterprise no; available in Payload Enterprise, or build your own
SCIM Enterprise not documented not supported no
Own certifications ISO 27001, SOC 2 Type 2 and more AWS and Stripe only, none of its own SOC 2 Type 2; ISO 27001 for Google Cloud none of its own; database and hosting providers have theirs, the application layer is on the team

For a SOC 2 or ISO 27001 audit, a team on Payload has to rely on the reports of its database and hosting providers: as with Prismic, the application layer has no certifications of its own, and the team is responsible for it.

API limits

With SaaS, the API limit is a quota on requests to the vendor’s servers; with Payload, the ceiling comes from your hosting and database.

Per Contentful’s Technical Limits, the Content Delivery API, which your site uses to read content, accepts 55 requests per second per space on Free and 78 on paid plans. Responses served from the CDN cache don’t count toward the limit (Content Delivery API reference). “Unlimited API calls” on Enterprise (pricing) also hit these ceilings: calls on Premium and Enterprise “do not accrue overages, and are bound by our technical limits” (usage limits). On the pricing page, Free includes 100,000 API calls and 50 GB of CDN bandwidth a month with no overage allowed, and Lite ($300 a month) includes 1 million calls and 100 GB, with overage at $5 per million calls and $0.15 per GB (usage limits). We break the plans down in our Contentful pricing article.

Prismic’s delivery limit is “200 non-cached requests per second per repository”. The Migration API, used to load content in, is stricter: “Requests are limited to one per second per repository”.

Per Sanity’s technical limits, the API accepts up to 500 requests per second per IP, and up to 25 per second each for mutations and file uploads; beyond that you get a 429 response. Responses served from the CDN cache have no rate limit but count toward the monthly quota. When the quota runs out on Free, the public API returns a 402 error, and content on the site won’t load until the start of the next month (UTC) or until you upgrade to Growth. Per the pricing page, Free includes 10,000 documents, 250,000 API requests and 1 million CDN requests a month. Growth costs $15 per seat a month with the same request quotas, and overage is billed ($1 per 25,000 API requests, $1 per 250,000 CDN requests, $0.30 per GB of bandwidth). Documents are a hard cap even on Growth: 25,000, with more only through a $299-a-month add-on.

Free infrastructure plans are just as strict: Vercel Hobby pauses the project when you exceed limits, and the site returns 503, while Neon Free suspends the database until the next month. On top of that, the Vercel ToS limit Hobby to use “for your personal or non-commercial use”.

In Payload, server code in the same deployment reads content through the Local API, with no vendor quota. A frontend on a different stack calls the REST or GraphQL API of your own app, and the ceiling comes from function resources and the database. On Vercel, the function request body is limited to 4.5 MB, so form attachments on TWG are capped at 4 MB in total. Vercel Blob bills bandwidth for every file served, so TWG caps media library uploads itself: 100 MB for video and 20 MB for other files (Blob itself accepts files up to 5 TB). One full view of a video means up to 100 MB of paid bandwidth. Blob also has a limit on the number of operations: 120 simple and 75 advanced operations per second on Pro, 20 and 15 on Hobby.

Payload 2 had built-in rate limiting, and Payload 3 removed it: “Removal of rate-limiting”. The abuse prevention page still lists lockout after failed logins (maxLoginAttempts), query depth and complexity limits, and CORS and CSRF settings. Since release 3.90.0, Payload also throttles password reset requests. Public forms can be protected from bots at the hosting level, for example with Vercel BotID, a service that detects automated requests.

Limit Contentful Prismic Sanity Payload on Vercel + Neon
Reading content 55 / 78 req/s per space (Free / paid), cache excluded 200 non-cached req/s per repository 500 req/s per IP to the API; CDN cache has no rate limit but counts toward the monthly quota no CMS quota; functions and database set the ceiling
Writing CMA 7 / 10 req/s Migration API 1 req/s (loading into Prismic) 25 req/s each for mutations and uploads limited by database and function resources
Exporting CLI and CMA (7 / 10 req/s) through the Content API (200 req/s) standard export, counts toward the API quota pg_dump and the Blob SDK
Abuse protection on the vendor on the vendor on the vendor on the team

Without rate limiting, a spike of uncached traffic goes straight to your functions and database and lands on your hosting bill. At Contentful and Sanity, requests over the rate limit get a 429.

Extending the CMS: hooks, endpoints, plugins

Extension points in Contentful, Prismic and Sanity

With SaaS, custom fields and server-side logic are limited to the vendor’s extension points. Contentful apps embed into the web app as iframes in seven designated locations. Server code can run through Functions, but “Functions are only available for Premium plans and Partners”, and they run in a sandbox without the fs and http modules, with a limit of 30 seconds per execution (10 seconds for resource.* function types) and 128 MB of memory.

Prismic has a fixed set of field types. The closest thing to a custom field is the Integration field, which pulls data from an external source. The docs don’t describe any way to run server-side code inside Prismic.

With all three SaaS vendors, custom server-side logic usually hooks in through webhooks that call your own infrastructure. Webhooks are asynchronous: they fire after the change, and each vendor handles retries differently (Contentful, Prismic, Sanity). Payload hooks run inside the request itself: if a hook returns a Promise, Payload waits for it. That’s why beforeChange can reject a write before it’s saved, and why a slow hook slows down the request (hooks).

Sanity is closer to Payload here. Studio is a React app under MIT: you write editor fields, panes and plugins in your own code and host Studio anywhere. But Studio “connects with Sanity’s hosted APIs and Content Lake”, and server code in Sanity Functions runs on the vendor’s infrastructure, for up to 900 seconds, with its Content Lake requests counting toward the same API quota.

In Payload, extensions are code in your repository

The Payload docs describe a plugin as a function that modifies the config: “a plugin is a function that receives a config and returns a modified config”. Besides plugins, there are hooks on collection and field operations, custom endpoints and custom admin components.

TWG uses official plugins (SEO, redirects, nested docs, Blob storage and MCP), our plugins (block presets, comments, scheduled publishing) and two written specifically for the project. The MCP plugin lets AI agents read and edit content over MCP (Model Context Protocol, an open protocol for connecting AI agents to external systems). Contentful, Prismic and Sanity also have official MCP servers, which the vendors host and maintain. With the Payload plugin, the team decides what each API key is allowed to do.

Form submissions go through a custom endpoint instead of the official Form Builder plugin. It filters out bots, validates the request body with Zod, accepts only attachments with allowed extensions and a total size of up to 4 MB, and sends the email through Resend:

// apps/payload/src/app/(payload)/api/form-submit/route.ts (shortened)
export async function POST(req: Request) {
  const verification = await checkBotId()
  if (verification.isBot) {
    return NextResponse.json({ error: 'BOT_DETECTED' }, { status: 403 })
  }

  const form = await req.formData().catch(() => null)
  const data = form?.get('data')
  const json = typeof data === 'string' ? parseJson(data) : null
  const parsed = BodySchema.safeParse(json) // Zod schema: action, recipientId, payload
  if (!form || !parsed.success) {
    return NextResponse.json({ error: 'INVALID_BODY' }, { status: 400 })
  }

  const files = form.getAll('attachments').filter((value) => value instanceof File)
  if (!areAllowedAttachments(files)) {
    return NextResponse.json({ error: 'INVALID_ATTACHMENT' }, { status: 400 })
  }

  const { action, recipientId, payload } = parsed.data
  // … files become Buffers, the email goes out through Resend
  const sendResult = await sendFormSubmissionEmail({ action, recipientId, payload, attachments })
  // …
}

Your own endpoints and other people’s plugins

Payload doesn’t secure your custom endpoints: “Custom endpoints are not authenticated by default. You are responsible for securing your own endpoints” (docs). The form endpoint in the listing is public, so instead of authentication it relies on bot checks, validation and an allowlist of file types.

When a bug turns up in someone else’s plugin and the fix hasn’t shipped yet, you patch the plugin locally and pin the version, then carry the patch forward on every update. Every plugin adds attack surface, official ones included. In 2026, a remote code execution vulnerability was found in the official Form Builder, rated CVSS 10 (the top of the scale) by Payload itself.

The cost of ownership: patches, paid plans, editors and new owners

This article doesn’t calculate total cost of ownership (TCO): it depends on salaries, pricing plans and content volume. Below is what the SaaS subscription used to include, what the team now does or pays for, and which providers in the stack have changed hands.

Patches and updates across the stack

So far in 2026 (as of November 1), the Payload repository has published 49 security advisories: 8 critical, 23 high and 18 medium, by Payload’s own rating. Of these, 22 came out on September 18 together with release 3.90.0. Before 2026, the repository had one, and the GitHub Advisory Database holds a few older entries for the package. Two of the eight critical ones affected official plugins, Form Builder and Import/Export. This number can’t be compared with SaaS directly: there, the vendor fixes vulnerabilities on its side.

Some updates also need a database migration. The 3.90.0 release notes say: “If you are using a relational database, you will need to create and run a migration”. On Postgres, the upgrade looks like this:

# package.json: payload and all @payloadcms/* packages on the same version, 3.90.0 or later
pnpm install
pnpm payload migrate:create    # new columns from the release, including for password reset
pnpm payload generate:types
pnpm payload migrate           # on every environment, production included

Patching covers the whole stack. A team with a Next.js frontend already patches Next.js, but with Payload, a Next.js vulnerability also reaches the admin panel, which has access to the CMS database. CVE-2025-29927 in Next.js middleware affected apps served with next start or in standalone mode. It didn’t affect projects on Vercel, where routing runs in a separate system. For CVE-2025-55182 in React Server Components, hosting providers rolled out temporary mitigations, but the React team warned: “You should not depend on these to secure your app, and still update immediately”.

In the 12 months up to November 1, 2026, Payload shipped 47 stable 3.x versions (per npm). There’s no official long-term support (LTS) policy. The Payload 4 migration guide lists close to a hundred sections of breaking changes (97 as of November 1, 2026).

Payload’s own weak spots

Patches aside, Payload has other limitations:

  • The admin panel is built on the Next.js App Router, and Payload pins the allowed Next.js versions tightly (peer dependency), so Payload and Next.js get updated together. A frontend on another stack doesn’t get you out of Next.js: the admin still lives there.
  • On serverless, running migrations automatically “may slow down serverless cold starts on platforms such as Vercel” (docs), and scheduled jobs need an external cron.
  • There’s no collaborative editing, only document locking while someone edits.
  • Version history from a SaaS CMS can’t be officially migrated. Payload keeps up to 100 versions per document by default (versions), and they live in the same database.
  • Payload 4 is in beta, so a project starting on 3.x has a major upgrade ahead.
  • Custom code (login, endpoints, plugin patches) can only be maintained by people who know it. If a contractor wrote it, fixes and updates depend on that contractor.

What you’ll buy or build separately

As with SaaS vendors, some features at managed providers are sold on higher-tier plans. Per Neon’s pricing, point-in-time recovery (PITR) is limited to 6 hours on Free, goes up to 7 days on Launch and up to 30 days on Scale, and SOC 2 report access and a service-level agreement (SLA, 99.95%) are available only on Scale. Vercel offers an SLA (99.99%) only on Enterprise, not on Pro ($20 a month per developer seat). With Contentful, a contractual SLA is also arranged separately: the uptime percentage goes into the Service Order, the order for that specific customer (SLA). Sanity offers an SLA only on Enterprise (99.9% or 99.95% depending on the plan), with service credits as compensation.

On top of that come everyday operations: monitoring, checking that backups actually restore, incident response. Payload sells commercial support as part of Enterprise, but prices and support terms aren’t published: the page only offers a demo and a sales contact.

What changes for editors

Payload’s core includes drafts, version history and localization, with no plan limits on the number of locales. Scheduled publishing is there too, but it won’t run without a job queue runner: “If you do not have any mechanism in place to run jobs, your scheduled publish / unpublish jobs will never be executed”. The runner can be a cron job on your host. Approval workflows and inline feedback on entries aren’t in the core; they’re listed among Enterprise features. Payload’s docs don’t describe releases. At Contentful, workflows, releases and custom roles also depend on the plan, but the features themselves are part of the service. Sanity offers custom roles only on Enterprise.

Feature Contentful Prismic Sanity Payload (open source)
Live preview yes, frontend connects via an SDK yes, needs preview routes in the frontend yes, on all plans yes, the team wires up the frontend
Click-to-edit on the page yes (inspector) partial: slice previews in Page Builder and a link from the preview to the document yes, on all plans not in the core; Visual Editor announced for Enterprise, third-party plugins exist
Collaborative editing presence and parallel editing of different fields in one entry (Live collaboration on Lite and up) not documented character-level, with presence, on all plans no, only document locking
Image transformations on a CDN Images API imgix via URL no; sizes are generated on upload, CDN is on the team

This is where SaaS is stronger: visual and collaborative editing and image processing come with the vendors’ services, while open-source Payload either lacks them or leaves them to the team. Live preview on all four requires code in the frontend.

Open-source plugins, including ours under the MIT license, add field comments, click-to-edit on a Next.js page and AI translation. They’re dependencies like any other: each one gets updated with the core and has to be checked against Payload 4.

Ownership changes: Contentful, Neon, Payload

Salesforce acquired Contentful in September 2026 to integrate it into its Customer 360 CRM platform, while Databricks acquired Neon in May 2025.

Payload joined Figma in June 2025. It remains open-source under an MIT license, meaning a team can fork and maintain released versions themselves if the repository owner ever changes the license for future versions. However, the acquisition has impacted infrastructure: Payload Cloud is currently not accepting new projects. Instead, Figma is building Payload hosting directly into Figma Make, which is currently in beta.

Case Study: A Contentful to Payload Migration (Glimble)

Our team moved Glimble from Contentful to Payload: we migrated 49+ components, built 30+ new ones and set up five access roles. As we describe in our breakdown of the Salesforce–Contentful deal, the project had around 2,000 pages and a Contentful bill of roughly €1,500 a month. The move took about two months. Running costs dropped to €100–150 a month. That figure doesn’t include engineering time for the move or ongoing maintenance. One more caveat from the same breakdown: the move coincided with a redesign that was already funded.

When moving makes sense and when SaaS is the better fit

A SaaS CMS comes out ahead in these situations:

  • The frontend isn’t on Next.js, or there are several channels (a website, a mobile app). The Local API doesn’t help then: Payload works as a separate backend over REST or GraphQL, and its admin still has to run as a Next.js app.
  • A large editorial team needs collaborative editing and visual page building out of the box. Sanity has both on all plans; open-source Payload doesn’t.
  • You need image transformations on a CDN without running your own infrastructure.
  • A client contract requires SOC 2 or ISO 27001 certification from the CMS provider itself.
  • There’s no developer on the team to maintain the CMS and nobody to handle incidents.
  • You want a single contract and a single vendor review. With SaaS, that’s the CMS vendor; with Payload on managed hosting, there are several providers, and overall availability depends on each of them.
  • The one-time cost of the move (switching the frontend off the vendor SDK, converting rich text, preserving URLs, retraining editors) isn’t justified without another reason, such as a redesign.

Moving makes sense when the SaaS CMS gets in the way in at least one of the four areas (data and exit, security and region, API limits, extensibility) and that limitation costs more than the work described in the cost of ownership section. Payload itself says in its use cases section that “it might not be the right choice for every project”.

Ready to take control of your CMS infrastructure?

Leaving a SaaS vendor for a self-hosted CMS gives you ultimate control, but it requires a specialized engineering team to get the architecture right. Learn how Focus Reactive helps companies executeEnterprise Payload CMS Migrations(or your Payload-specific URL), from custom Next.js integrations to scalable Neon database deployments.

FAQ

Can I use Payload in a commercial project for free?

Yes. Payload's code is distributed under the MIT license. Enterprise features, including SSO, are sold separately.

Is it still self-hosted if Payload runs on Vercel and Neon?

In the sense this article uses, yes: the team owns the code, the schema and the database. The servers are managed, though, and subject to those providers' limits and pricing.

Does Payload have built-in rate limiting?

Not as a general feature in Payload 3: it was removed in the move from version 2. What remains is lockout after failed logins, query depth and complexity limits, and, since 3.90.0, password reset throttling. Any other protection goes in at the hosting level or in your own code.

Sanity Studio is open source. How is that different from Payload?

At Sanity, the Studio editor and the client libraries are open source under the MIT license. The content lives in Content Lake, which is closed and runs only as Sanity's service: the contract, the region, API quotas and plan-dependent edit history retention all stay with the vendor. With Payload, both the admin and the storage layer are open, and the database is yours.

How do I export content from Contentful?

The standard CLI exports entries, assets, the content model and roles, but not version history, workflows, comments or releases Contentful help center. You have to pull everything else with your own code through the Content Management API, within its limits.