Production WordPress Should Be Read-Only
A plugin install is a dependency decision. Production is the worst place to make one.
- Deployment
- DevOps
- Production Environments
- Security
- Technical Debt
- WordPress
Production WordPress should be read-only.
Not mostly read-only.
Not read-only unless someone really needs to install a plugin quickly.
Read-only.
If your WordPress production environment allows plugin installs, theme edits, and ad hoc code changes, you don’t really have a production environment. You have a live workshop.
And that’s exactly where a lot of WordPress sites get into trouble.
The problem with a live workshop
It usually starts innocently enough.
A plugin gets installed to solve an urgent problem. Someone edits a theme file through wp-admin. A vendor adds a temporary CSS or JavaScript fix because staging is inconvenient. Someone installs WP File Manager because they need quick access to the server.
Each decision seems small. Sometimes it even solves the immediate problem.
Six months later, nobody knows what changed, why it changed, whether the change exists in Git, whether staging matches production, or whether any of it will survive the next deployment.
And the next person who touches the system inherits all of those decisions without knowing they were made.
This isn’t just a security issue, although it’s absolutely that. It’s an operational issue.
Once production can change independently of the codebase, you no longer have a reliable answer to a very basic question: What are we actually running?
A plugin install is a dependency decision
WordPress makes installing software ridiculously easy. Find a plugin, click Install, activate it, and you’re done.
Except you’re not.
You’ve introduced someone else’s code into a production application. It may bring new database tables, background jobs, scheduled tasks, JavaScript, third-party requests, configuration, and an ongoing patching obligation.
It might overlap with functionality you already have. It might be abandoned in a year. It might behave differently with your caching layer or a future version of PHP.
None of that makes plugins inherently bad. WordPress’s plugin ecosystem is one of its greatest strengths.
But a plugin install is not a click. It’s a dependency decision. And production is the worst possible place to make dependency decisions.
That decision belongs in the same process as any other application change: understand the requirement, evaluate the dependency, test the behavior, record the change, and deploy it deliberately.
Read-only code doesn’t mean read-only content
There’s an important practical point here: I’m not arguing that editors should have to open a pull request to correct a headline or publish an article.
WordPress is a content management system. Content needs to remain manageable.
Editors should still be able to create and revise posts, update pages, manage appropriate media, and work through the normal publishing process. Those are the things the CMS is there to do.
What shouldn’t happen through the production admin is changing the application itself.
| Editorial work | Application changes |
|---|---|
| Edit a page or post | Install a plugin |
| Publish a new article | Update plugin or theme code |
| Upload approved media | Edit PHP or theme files |
| Review revisions and drafts | Introduce a new executable dependency |
| Update content within the existing design system | Change the application’s deployed source |
The first column is ordinary CMS work. The second belongs in development, source control, testing, and deployment.
Read-only refers to application code, not the WordPress database or every writable directory. Media uploads, caches, logs, and other runtime data may still need to be writable. The goal is to stop production code from drifting away from the version we’ve tested and deployed.
Two lines that remove a surprising amount of chaos
On the WordPress sites we manage, the starting point is straightforward. In wp-config.php:
define( 'DISALLOW_FILE_EDIT', true );
define( 'DISALLOW_FILE_MODS', true );
DISALLOW_FILE_EDIT disables the built-in plugin and theme file editors. DISALLOW_FILE_MODS goes further, preventing plugin and theme installs and updates through WordPress’s administration workflow, as well as file editing.
Technically, the second constant already covers the first. I like showing both because the intention is unmistakable: production is not where we edit or install code.
These are standard WordPress configuration options, not some custom security workaround. They’re documented in the WordPress administration handbook.
There’s one consequence that needs to be planned for: file-modification restrictions also affect WordPress-managed update mechanisms. If you lock these down, you need another reliable way to deploy core, plugin, and theme updates. That includes urgent security patches.
These constants enforce WordPress-level behavior; they do not make the server filesystem immutable. They don’t stop every possible filesystem write, a compromised PHP process, or someone with direct server access. Filesystem permissions, hosting controls, access management, and deployment discipline still matter.
Changes should flow toward production, not originate there
Once you decide that production isn’t a workshop, the process becomes fairly ordinary:
- Evaluate the change. What problem does it solve, and do we really need another dependency?
- Make it in the codebase. Use a local environment and record application changes in version control.
- Test it before release. Validate behavior in staging, including compatibility with the rest of the system.
- Deploy deliberately. Move the tested change to production through a repeatable process.
- Verify and retain a rollback path. Know what went out, when it went out, and how to undo it if necessary.
A security emergency doesn’t invalidate the model. It means you need a faster version of the same controlled process, not an undocumented exception that leaves production different from everything else.
And this is not exclusively a WordPress problem. WordPress is just an especially visible example because it exposes so much production-changing power directly through its administrative interface.
Any application that allows its live environment to drift away from source control and its deployment process will eventually suffer the same problem.
The goal is to make production boring
I’ve written before about why I still review WordPress plugin updates personally. That isn’t at odds with this approach. Reviewing dependencies is a maintenance responsibility. Installing or editing them directly on the live site doesn’t have to be.
For me, the value is knowing what’s there, why it’s there, and whether it still earns its place. Version-controlled deployment makes that knowledge useful because the environment you’re reviewing actually corresponds to the application you’re maintaining.
The goal isn’t to make WordPress harder to use.
The goal is to make production boring.
No mystery plugins. No one-off theme edits. No emergency browser-based code changes that nobody remembers making. No guessing whether the next deploy will erase something important.
Because once production becomes a place where anyone can improvise, you lose the thread. You lose repeatability. You lose confidence in deployment. Eventually, you lose the ability to explain the system you’re responsible for.
A real production environment should be boring, controlled, and reproducible.
If it isn’t, it’s just the live site.