Drupal's flexibility is a cost as well as a feature: every door it leaves open is one somebody has to decide about, review, document and keep maintained. The market's hesitation about Drupal usually gets written off as a marketing problem. More often it is an accurate reading of that cost — and the answer is not to defend the flexibility harder, it is to close the doors your project does not need, on purpose, early.
That is a different subject from the learning curve. If your question is how long it takes to become productive, the realistic first ninety days covers the order to learn things in. This page is about what the openness costs a project after everyone already knows how to use it.
Where the cost actually lands
Several valid ways to build the same page
A piece of content on a Drupal page can arrive as a block placed in a theme region, a content block referenced from a layout, a Paragraph inside a node field, a view embedded in a display, or a field rendered directly. All of them are correct. None is wrong enough for the platform to object.
The bill arrives when somebody has to change that page and cannot tell which mechanism put each piece there. The clearest measurable version is the duplicate that appears when a block is placed in a region and also referenced from a Paragraph: it renders twice, Drupal is obeying both instructions, and nothing flags a conflict because there is not one.
Structure everyone can change is structure nobody owns
In a default installation, anyone with the right permission can add a content type, add a field or build a view — in production, in a browser, with no review. Individually each is a two-minute convenience. Cumulatively they are how a site reaches nineteen content types where six were designed, and a field list nobody can explain.
The cost is already inside the estimate
Flexibility is one reason two agencies quote very differently for the same brief: one is pricing the build, the other is pricing the decisions. That is worth understanding before comparing numbers, and it is covered in what a Drupal website actually costs.
The switches core gives you to close doors
The useful thing about constraining Drupal is that nothing has to be invented. The mechanisms are in core, and every one below was read from Drupal core 11.4.6 on disk.
| What you want to prevent | The core mechanism | Where it is defined |
|---|---|---|
| Day-to-day roles changing the content model | The administer content types permission | core/modules/node/node.permissions.yml |
| Ad-hoc view building on production | The administer views permission — and Views UI is a separate module that can simply be uninstalled | core/modules/views_ui/ |
| Field changes made through the browser | Field UI is optional: its info file declares only a dependency on drupal:field, and Field itself keeps working without it |
core/modules/field_ui/field_ui.info.yml |
| Arbitrary markup from the editor | The Limit allowed HTML tags filter, plugin id filter_html |
core/modules/filter/src/Plugin/Filter/FilterHtml.php |
| The wrong people holding a permissive format | A permission generated per format, in the form use text format <id> |
core/modules/filter/src/Entity/FilterFormat.php |
| Every node having its own bespoke layout | Layout Builder's per-display allow_custom setting, off unless you turn it on |
core/modules/layout_builder/src/Entity/LayoutBuilderEntityViewDisplay.php |
| Structure changing without review | Export configuration to the directory named by $settings['config_sync_directory'] and require the change to go through the repository |
sites/default/default.settings.php |
A worked example: what basic_html already refuses
The basic_html format installed by the standard profile carries an explicit allowed-tag list, and it is shorter than people expect. It permits paragraphs, headings from h2 down, lists, definition lists, links, blockquotes, code, strong, em, cite and images. It does not permit <table>, <div> or <span>.
That is a constraint doing its job, and it is also the failure people hit without understanding it: write a correct, semantic table into a field using that format and the markup does not survive the render. Nothing warns you. Deciding which formats exist, and which role gets each, is one of the cheapest structural decisions available and one of the least often made deliberately.
Choosing which doors to close is architecture work rather than configuration work — the Drupal architect page covers the decisions in this family that are expensive to reverse once content has accumulated on top of them.
Defaults are open, so restraint has to be somebody's decision
Counted on disk in 11.4.6: core ships 75 module directories and 32 distinct field types before a single contributed project is added. Nothing in a standard installation suggests using only a fraction of that, and nothing objects when you use all of it.
So the decision has to be written where a person will read it — half a page naming which content types exist and what each is for, which page-building mechanism this site uses, which text formats exist and who holds them, and what has to happen before a new content type is created. That is the difference between a model and an accumulation.
When the openness is worth paying for
None of this argues for a simpler platform. The test is concrete: can you name three different places one piece of content has to appear — a page, a listing, a feed, another system, another language? If you can, the flexibility is already earning, and constraints only stop it being spent elsewhere.
If you cannot, and the site is pages you publish rather than data you model, the comparison worth reading is Drupal against WordPress on exactly that distinction. Paying for capability you will never use is a real cost, settled at every security release.
Constraining a site you already have
On an existing site the order matters, because removing capability from people using it produces a revolt rather than a model.
- Inventory first — you cannot sensibly remove a permission before knowing who uses it and for what, which is what a week-one diagnostic establishes.
- Move structural permissions off the day-to-day roles, keeping one administrative role that can still do the work.
- Export configuration into the repository, so a structural change becomes a reviewable event instead of an invisible one.
- Decide the text formats, then check which roles hold the permissive one.
- Only then consider uninstalling the interface modules in production, and only once configuration genuinely deploys from code.
Common questions
Is constraining Drupal fighting the platform?
No — every switch above is core's own, and several ship off by default precisely because the project expects you to decide. Layout Builder's per-item override is the clearest example: you have to turn it on.
Will editors resent losing capability?
Usually only where something they actively used disappears. Check the permissions page before changing anything. Removing a capability nobody has used in a year is invisible; removing one somebody uses weekly is a conversation you should have first.
Is this what people mean when they say Drupal is complicated?
Partly. The complaint that gets stated is the learning curve; the one that costs money is the decision surface — the number of reasonable ways to do each thing, and the absence of a default opinion about which. The first is temporary. The second is permanent unless you close it yourself.
Can a small site skip all of this?
It can skip the documentation and still not skip the decisions. Two people building a ten-page site should agree on one page-building mechanism rather than three, because the cost of mixing them scales with how long the site lives, not with its size.
Does constraining a site make upgrades harder?
The opposite, in my experience. Fewer mechanisms in use means fewer things to test at a major version, and configuration in the repository means an upgrade can be rehearsed somewhere that is not production.
Where to go next
If you are starting a build, these constraints are cheapest now and most expensive to retrofit. If you have inherited a site that has already drifted, the first step is finding out what is there rather than guessing — that is what a consulting engagement is for. Either way, describe the site and what keeps going wrong, and you will get an honest answer about whether the problem is Drupal's flexibility or something much more specific.