Comparison and Decision Guide

This content was generated with the assistance of AI and should be verified against the official Drupal documentation before being relied on in production.

This sub-section’s Drupal bibliography lists the reference material consulted while preparing these pages.

Drupal offers several ways to do almost everything, and most of the early decisions of a project are a choice between two or three of them. This page gives a table and a rule of thumb for each such choice, then says when Drupal is the wrong tool altogether. It was checked on 2026-10-30 against Drupal 11.4.x, Drush 13 and 14, and PHP 8.3 or later. Drupal 10 reaches end of life on 2026-12-09 and Drupal 12.0.0 is planned for the week of 2026-12-07, so both are future dates from the point of view of this check; a new site starts on Drupal 11, and this page does not recommend Drupal 10.

The running example is the Meridian Museum, a fictitious regional science museum with exhibitions, events, news and a collection of objects, an English and Spanish site, and a gallery kiosk. Each section ends with the choice the museum makes. For cross-CMS metrics (market share, security record, talent pool, cost) see the CMS Comparison, which is not repeated here. The decisions below are about choices inside Drupal.

Drupal core versus Drupal CMS

Drupal core is the framework and a minimal installation profile. Drupal CMS is a curated distribution of Drupal 11 that is assembled from recipes (a recipe is a package of configuration and dependencies applied once; see Recipes). It is not a fork: it is core plus contributed projects plus a pre-configured experience. Version 2.x makes Canvas the default editor and offers the site templates Byte, Starter (with the Mercury theme) and Blank, with an optional AI Assistant. Version 1.x is unsupported, and the documentation lives at project.pages.drupalcode.org/drupal_cms. Recipes have no update path: once applied, the site is an ordinary Drupal site, and you maintain it with Composer and Drush like any other. See Drupal CMS and Site Templates.

Criterion Drupal core Drupal CMS

Starting point

A minimal site (the Standard profile no longer creates the Article and Page content types in 11.4)

A working site from a site template, with editor, SEO, forms and accessibility defaults chosen for you

Editor experience

Whatever you build: content forms, Layout Builder, Paragraphs, Canvas

Canvas by default in 2.x

Control and size

You add only what you need; a smaller attack surface and a longer first build

More modules and recipes on day one that you may remove or keep

Learning value

You see every decision

Faster result; you still need core knowledge to change things

Upgrades

Composer, drush deploy, security releases

The same, because the result is ordinary Drupal

Rule of thumb. Choose Drupal CMS when a small team wants a good-looking, editor-friendly site quickly and has no strong opinion about the architecture. Choose core when the data model is the product, as with the museum’s collection, or when the project must pass a review of every installed module. The museum starts from core because it has a custom content entity and a curated roles model; a smaller museum partner site could start from a Drupal CMS template.

Layout Builder versus Canvas versus Paragraphs

These three address the same editorial wish, a page that is more than one text field, in different ways.

  • Layout Builder is a core module. It places blocks and fields into sections, per content type or per node, and stores the layout in configuration (per content type) or in a field (per node). See Layout Builder.

  • Canvas (formerly Experience Builder) is a contributed module, at 1.0 since December 2025 and at 1.12 on the check date, and it requires Drupal 11.3 or later. It composes pages from Single Directory Components and from code components written in JavaScript and CSS and rendered with Preact through its React compatibility layer. See Canvas.

  • Paragraphs is a contributed module that adds reorderable, typed content chunks to an entity reference revisions field, so editors fill structured parts instead of laying out a page. Its current release works with Drupal 10.3 and Drupal 11.

Criterion Layout Builder Canvas Paragraphs

Where it lives

Core

Contrib; Drupal CMS 2.x default

Contrib

Editing model

Place blocks into regions of a section, per type or per node

Drag components, edit props and slots in a live page

Add, reorder and fill typed chunks in the node form

Best for

Landing pages, per-node layouts for a few content types

Marketing and visitor-facing pages assembled by non-developers

Long, structured, repeatable content (a gallery of objects, an accordion)

Developer effort

Block plugins, templates, access and cache care

SDC components and code components

Paragraph types, field formatters and templates

Risk

Per-node overrides are hard to migrate and hard to keep consistent

Younger module; check release notes before relying on a feature

Content and layout are tied to field structure and revisions

Drupal CMS 2.0 had no automatic migration from Layout Builder or Paragraphs content to Canvas, so choose with the next three years in mind and re-check the Canvas release notes before planning a migration. Layout Builder stays in core. The older books Drupal 10 Masterclass (2023) and Drupal 10 Development Cookbook (2023) present Layout Builder as the only visual builder; since Canvas, it is one of three options, and the right default depends on who edits the page.

Rule of thumb. Use Paragraphs when the content is structured and repeated, Layout Builder when a few page types need bespoke layout and you want to stay on core, and Canvas when non-developers assemble varied pages from a component library. The museum uses structured content types and Views for exhibitions and objects, and Canvas for its home and campaign pages, with the ticket-banner code component.

Custom module versus contrib

A contributed module is maintained by the community and reviewed by the Security Team when it has a stable release that opts in to security coverage. A custom module is code your team owns forever.

Question Prefer contrib when Prefer custom code when

Does it already exist?

A maintained project with a stable release and Drupal 11 support does the job

No project fits, or the fit needs patches you cannot upstream

Who maintains it?

Many sites depend on it, with active releases

It encodes your own domain, such as meridian_collection

Security

A stable release covered by Drupal’s security advisories policy

You accept the review, testing and update burden

Cost

Install, configure, track its updates

Design, write, test (see Automated Testing) and maintain

Exit

Replace with another module or remove

Rewrite or keep

Check before adopting a contributed project: the project page’s supported Drupal versions, its security-coverage badge, the date of its last release, its open issue queue, and whether it is the replacement for a module that was removed from core (see Removed Core Modules). Prefer a small contributed module and a small custom module over a large custom module that reimplements it. Whatever you write, follow Module Anatomy and the coding standards. Add Composer packages with composer require drupal/<project>, never by uploading code: module and theme upload from the UI was removed in 11.0 and 11.1.

Content entity versus node bundle versus custom table

Three places can hold the museum’s data.

Criterion Node bundle (content type) Custom content entity Custom database table

Created by

An administrator, in the UI, exported as configuration

A developer, with an entity type class and a schema

A developer, with hook_schema() or the Database API

Gets for free

Fields, forms, Views, revisions, translations, moderation, permissions, search, JSON:API

The same, once the entity type enables the features you need

Nothing; you write queries, forms and access yourself

Best for

Editorial content that needs the full CMS (exhibition, event, news)

A domain model with its own lifecycle and many records (the collection of objects)

Logs, counters, imports, data with no editorial or field behaviour

Cost

Low

A class, annotations or attributes, routes, permissions, handlers

High if the data later needs the entity features

The museum models exhibitions and events as node bundles, because editors, Content Moderation, Views and the front end expect them. It models the collection as a custom content entity, collection_object, with fields such as accession_number and period, because thousands of objects have their own list, access rules and import from a collection-management system, and do not belong in the editorial content list. A table of sync timestamps for that import is a custom table or state, since nobody edits it.

Rule of thumb. Start with a node bundle. Move to a custom entity when you need your own permissions, routes, storage or bulk lifecycle. Use a custom table only for data that will never need fields, translations or Views. See Content Types and Fields, Custom Entity Types and Database API and Entity Queries. Entity queries must call accessCheck() explicitly, whichever of the first two you choose.

JSON:API versus REST versus GraphQL

All three expose content to other programs. JSON:API is part of core and needs no configuration; the core REST module (with Serialization) is also in core and exposes resources you enable one by one; GraphQL (5.x) is a contributed module. Simple OAuth (6.x) is contributed too, and 6 removed the implicit and password grants.

Criterion JSON:API REST GraphQL

Where

Core

Core

Contrib, the GraphQL project

Shape

Resources per entity type and bundle, with filtering, sorting, paging and includes in the query string

Resources you enable and configure, one endpoint each

One endpoint, a schema, and the client chooses the fields

Setup

Enable the module; it is zero-configuration and read-only mode is available

Enable and configure resources, formats and authentication

Build and maintain a schema and resolvers

Writes

POST, PATCH and DELETE on the same resources

Per-resource methods

Mutations you define

Caching

Cacheable GET responses with cache metadata

Cacheable GET

Needs more design to cache well

Best for

Headless front ends over content entities

A few custom endpoints and legacy integrations

Clients that need precise, nested, cross-entity data

JSON:API follows the standard format with Drupal’s conventions, and business operations such as account creation, login and password requests are outside its scope. Because it exposes entities directly, bugs in the Entity, Field or Typed Data APIs can become security problems, so keep Drupal updated and use read-only mode where the front end only reads.

Rule of thumb. Default to JSON:API for the kiosk, because it needs no code and the museum’s gallery pages are read-mostly. Reach for REST only for a hand-shaped endpoint or an existing consumer. Add GraphQL when the client team needs to ask for deeply nested data in one round trip and agrees to maintain a schema. See JSON:API, REST and Serialization and GraphQL.

Starterkit theme versus subtheme

Since Drupal 10.0, Starterkit (php core/scripts/drupal generate-theme) is the way to start a theme: it copies a snapshot of the starter theme into your project, and it stays yours. A subtheme declares a base theme and inherits templates and libraries, which are updated when the base theme updates. Classy and Stable were removed in 10.0, and Stable 9 was deprecated in 11.4. Olivero, Claro and Stable 9 leave core in Drupal 12, and Default Admin, based on Gin, becomes the admin theme, so a theme that extends one of them as a base is the riskiest choice.

Criterion Starterkit-generated theme Subtheme of a base theme

Relationship

A copy with no ongoing link

A live dependency on the base

Upgrades

You carry the code yourself

Base-theme changes arrive, sometimes breaking

Control

Total

Limited by what the base allows

Risk in Drupal 12

Low

High if the base is Olivero, Claro or Stable 9

Best for

A bespoke site theme such as meridian

A deliberate extension of a maintained contributed base theme

Rule of thumb. Generate a Starterkit theme for a custom site theme. Use a subtheme only when you intend to track a maintained base and accept its updates. See Starterkit and Subthemes.

Config Split versus settings overrides

Configuration management exports the site’s configuration to YAML. Environments still differ (a dev-only module, a different email address, a disabled cache), and there are two ways to handle that.

  • Config Split is a contributed module. It defines splits, sets of configuration written to their own directories on export and merged with the main sync directory on import. Version 2.x, whose latest release at this check is 2.0.2 from February 2025, supports Drupal 8.8 through 11 and can split individual keys using a config patch. It filters the import and export pipeline and does not change active configuration. The splits that are active are chosen in settings.php.

  • Settings overrides are values in settings.php (the $config array) that override configuration at runtime without changing the stored configuration. They are not exported, which suits secrets and per-environment values and does not suit structural differences such as a module being enabled in one environment.

Criterion Config Split Settings overrides

Use for

Different module sets, different config objects, a dev-only configuration

Single values per environment, secrets from environment variables

Visible in the UI

Yes; the stored value is shown

The form shows the stored value while the override applies, which confuses editors

Exported

Yes, in the split directory

No

Secrets

Never put secrets in exported configuration

Read them from the environment

Cost

A contributed module and discipline about what goes where

None

// settings.php
$settings['config_sync_directory'] = '../config/sync';

// A value that differs per environment and must not be exported.
$config['system.mail']['interface']['default'] = 'test_mail_collector';

// Activate a split for this environment (the split is created with Config Split).
$config['config_split.config_split.dev']['status'] = (getenv('MERIDIAN_ENV') === 'dev');

Rule of thumb. Use settings overrides for a few scalar values and for anything secret, and use Config Split when whole objects or module lists differ. Do not use both to control the same value. See Configuration Management and settings.php and Environments.

Single site versus multisite

Drupal can serve several sites from one codebase, each with its own sites/<name> directory, settings and database (see Multisite).

Criterion Separate installs One multisite codebase

Isolation

Strong: separate code, database, deploys, failures

Shared code and PHP process; separate databases and files

Updates

One site at a time

One code update affects every site

Customisation

Free per site

Shared modules and themes; per-site settings only

Operations

More servers or containers to manage

Fewer codebases, trickier deploys and configuration

Tooling caveat

Fully supported

Automatic Updates does not support multisite

Rule of thumb. Choose separate installs, usually with containers (see Docker and Containers), unless the sites truly share code, release cadence and a team, such as a museum with a main site and satellite sites that differ only in theme and content. Multilingual needs, such as the museum’s English and Spanish site, are not a reason for multisite: use one site with translations, see Multilingual.

Traditional versus decoupled

A traditional Drupal site renders pages with Twig and the render system. A decoupled (headless) site uses Drupal as a content and API back end, and a separate front end, for example Next.js, renders the pages. Progressive decoupling sits between: Drupal renders the page and a JavaScript application owns a part of it.

Criterion Traditional Decoupled

Team

Drupal developers and themers

Back-end and front-end teams

Editing

In-context editing, Layout Builder or Canvas, preview, contextual links

Preview must be built; page builders do not render the external front end

Caching

Render cache, dynamic page cache, BigPipe, with cache metadata built in

A CDN and the front end’s cache, invalidated from Drupal

Security

One application, the usual hardening

Two applications, CORS, tokens and OAuth to design

Cost

Lower

Higher: two codebases, hosting and deployments

Best for

Editor-driven sites

Multiple channels, app-like experiences, a front-end team that wants its own stack

Rule of thumb. Stay traditional unless you need more than one front end or the front-end team will not work in Twig. The museum keeps its public site traditional and uses a decoupled Next.js app only for the gallery kiosk. See Decoupled Drupal with Next.js and Authentication and OAuth.

Decision tree

flowchart TD A["New web project"] --> B{"Content-heavy, with roles, workflows, languages or a custom data model?"} B -->|"no, a few pages"| W["Small brochure site: WordPress or Webflow"] B -->|"yes"| C{"Mostly application logic: carts, accounts, dashboards, custom flows?"} C -->|"yes"| L["Application framework such as Laravel, with or without a CMS"] C -->|"no"| D{"Need a quick editor-friendly start?"} D -->|"yes"| E["Drupal CMS with a site template"] D -->|"no, custom model"| F["Drupal core with custom modules"] E --> G{"Several front ends?"} F --> G G -->|"yes"| H["Decoupled: JSON:API, optionally GraphQL"] G -->|"no"| I["Traditional: Twig theme, Layout Builder, Canvas or Paragraphs"] H --> J{"Several sites sharing code and team?"} I --> J J -->|"yes"| K["Multisite or a shared distribution"] J -->|"no"| M["One site, Config Split or settings overrides per environment"]

When Drupal is not the right tool

Drupal pays back its learning curve when a site has structured content, roles, workflows, multilingual content and a long life. It is a poor fit in these cases.

  • A small brochure site with a handful of pages, edited by one person, and no custom data. The cost of Composer, updates, hosting and a developer is out of proportion. Look at the WordPress or Webflow sub-sections, which also compare their own strengths; the CMS Comparison has the cross-CMS metrics.

  • A complex application where the work is business logic, not content: transactions, dashboards, workflows without editors. Use an application framework; see the PHP and Laravel section. Drupal can still serve the content part of such a system through an API.

  • A shop as the main product. Shop extensions for Drupal exist, but selling is a different problem; compare dedicated platforms first in the E-commerce comparison.

  • No technical skills or hosting to keep Composer-based updates and security releases going. Drupal expects an administrator who can apply security releases; Automatic Updates covers patch-level core updates only.

  • Very short projects where the time to learn the platform exceeds the time to build the site.

Common mistakes

  • Building a custom entity for editorial content that a node bundle would handle, and then re-implementing revisions and moderation.

  • Using a contributed module without checking its Drupal 11 support or security coverage.

  • Overriding the same setting in Config Split and in settings.php, so nobody can tell which value applies.

  • Choosing a base theme that leaves core in Drupal 12.

  • Going headless for a site with a single front end, and then rebuilding preview, forms and caching by hand.

  • Choosing multisite to get translations.