The File That Can Kill Your Site in One Keystroke
Every WordPress installation has exactly one file where a single missing semicolon takes down the entire site. No error message. No admin panel. No recovery path from the browser. Just a white screen, or if you're lucky, a cryptic PHP parse error that only appears if display_errors happens to be on.
That file is wp-config.php.
I've been working with WordPress for over 15 years, and I still treat this file with respect every time I open it. Not because it's complex — it's actually one of the simplest files in the codebase. It's just a list of PHP constants. But it's loaded before everything else, before WordPress core, before any error handling, before any plugin that might catch problems gracefully. If wp-config.php has a syntax error, nothing runs. Nothing.
And yet, the standard advice in every WordPress tutorial is "just open wp-config.php and add this line." As if hand-editing a file that can instantly brick your site is no big deal.
This guide is the reference I wish existed when I started. Every constant explained, organized by purpose, with the actual values you should use and the mistakes that will get you a 3 AM phone call from a panicking client.
What wp-config.php Actually Does
When a request hits your WordPress site, wp-config.php is the first file that executes. It runs before wp-settings.php, before any plugin loads, before the theme initializes. It defines the constants that control everything downstream.
Here's the loading order:
- Web server receives request, starts PHP
-
wp-config.phploads — defines database credentials, security keys, and behavior constants -
wp-config.phpincludeswp-settings.php -
wp-settings.phpbootstraps WordPress core - Plugins load
- Theme loads
- Template renders
Because wp-config.php runs first, it controls things that can't be changed later. Once a PHP constant is defined with define(), it can't be redefined. A plugin can't override your WP_DEBUG setting. A theme can't change your database credentials. Whatever you put in wp-config.php is final.
The file also serves as the connection between WordPress and your specific environment — your database, your server paths, your security configuration. Two identical WordPress installations can behave completely differently based solely on their wp-config.php files.
The Anatomy of wp-config.php
A default wp-config.php has a specific structure, and the order matters more than people realize. Here's the skeleton:
<?php
// ** Database settings ** //
define( 'DB_NAME', 'wordpress' );
define( 'DB_USER', 'root' );
define( 'DB_PASSWORD', 'password' );
define( 'DB_HOST', 'localhost' );
define( 'DB_CHARSET', 'utf8mb4' );
define( 'DB_COLLATE', '' );
// ** Authentication keys and salts ** //
define( 'AUTH_KEY', 'unique-phrase-here' );
define( 'SECURE_AUTH_KEY', 'unique-phrase-here' );
define( 'LOGGED_IN_KEY', 'unique-phrase-here' );
define( 'NONCE_KEY', 'unique-phrase-here' );
define( 'AUTH_SALT', 'unique-phrase-here' );
define( 'SECURE_AUTH_SALT', 'unique-phrase-here' );
define( 'LOGGED_IN_SALT', 'unique-phrase-here' );
define( 'NONCE_SALT', 'unique-phrase-here' );
// ** Table prefix ** //
$table_prefix = 'wp_';
// ** Custom constants go HERE ** //
/* That's all, stop editing! Happy publishing. */
/** Absolute path to the WordPress directory. */
if ( ! defined( 'ABSPATH' ) ) {
define( 'ABSPATH', __DIR__ . '/' );
}
/** Sets up WordPress vars and included files. */
require_once ABSPATH . 'wp-settings.php';
The critical line is the comment: /* That's all, stop editing! Happy publishing. */
Every custom constant you add must go ABOVE that line. Below it, wp-settings.php gets included and WordPress starts bootstrapping. If you define a constant after require_once ABSPATH . 'wp-settings.php', WordPress has already loaded without your setting. The constant technically exists, but WordPress already made its decisions without it.
I see this mistake at least once a month. Someone adds define( 'WP_DEBUG', true ); at the very bottom of the file, below the require_once line, and wonders why debug mode isn't working. The constant is defined — but WordPress already checked for it and moved on.
Debugging Constants
These are the constants you'll reach for most often during development and troubleshooting.
WP_DEBUG
define( 'WP_DEBUG', true );
The master switch for WordPress debugging. When true, WordPress displays PHP errors, notices, and warnings that are normally suppressed. This is the first thing I enable when diagnosing any WordPress problem.
On a production site, WP_DEBUG should always be false. PHP notices reveal file paths, function names, and sometimes database structure — information that helps attackers. But on staging or development, it should always be true.
WP_DEBUG_LOG
define( 'WP_DEBUG_LOG', true );
When enabled alongside WP_DEBUG, WordPress writes all debug output to wp-content/debug.log. This is essential for catching errors on production without displaying them to visitors. You can also set it to a custom path:
define( 'WP_DEBUG_LOG', '/var/log/wordpress/debug.log' );
I keep a custom log path on every production site I manage. The default wp-content/debug.log is web-accessible unless you block it with .htaccess or nginx rules. A log file outside the webroot is safer.
WP_DEBUG_DISPLAY
define( 'WP_DEBUG_DISPLAY', false );
Controls whether debug output shows up on screen. The production debugging combo I use on every site:
define( 'WP_DEBUG', true );
define( 'WP_DEBUG_LOG', true );
define( 'WP_DEBUG_DISPLAY', false );
@ini_set( 'display_errors', 0 );
This captures every error in the log file without showing anything to visitors. The @ini_set line is a safety net — it suppresses display at the PHP level in case any code re-enables it.
SCRIPT_DEBUG
define( 'SCRIPT_DEBUG', true );
Forces WordPress to load the unminified versions of core CSS and JavaScript files. Useful when you're debugging core behavior or developing against WordPress's bundled scripts (like jQuery, wp.media, or the block editor). On production, leave this false — the minified versions are smaller and faster.
SAVEQUERIES
define( 'SAVEQUERIES', true );
Makes WordPress store every database query, along with how long it took and which function called it, in the global $wpdb->queries array. This makes detailed query data available to tools like Query Monitor for backtraces and timing analysis.
Never enable this on production. It stores every query in PHP memory for the lifetime of the request. On a page that runs 400 queries, that's a significant chunk of RAM. It also adds a backtrace call for every query, which slows things down further. Use it for debugging, then turn it off.
WP_DISABLE_FATAL_ERROR_HANDLER
define( 'WP_DISABLE_FATAL_ERROR_HANDLER', true );
WordPress 5.2+ includes a fatal error recovery mode that catches fatal errors and shows a "There has been a critical error on this website" message. This is helpful for users but annoying for developers because it hides the actual error. Setting this to true shows the raw PHP error instead, which is what you want when debugging.
Security Constants
These constants harden your WordPress installation. On any production site, most of these should be enabled.
DISALLOW_FILE_EDIT
define( 'DISALLOW_FILE_EDIT', true );
Removes the built-in theme and plugin code editors from the WordPress admin (Appearance > Theme File Editor and Plugins > Plugin File Editor). This is a must on production. If an attacker gains admin access, the first thing they do is use the theme editor to inject malicious code. Disabling the editor forces them to need FTP/SSH access, which is a much higher bar.
DISALLOW_FILE_MODS
define( 'DISALLOW_FILE_MODS', true );
Goes further than DISALLOW_FILE_EDIT — it also disables the ability to install, update, or delete plugins and themes from the admin panel. This is appropriate for locked-down production environments where deployments happen through Git or CI/CD pipelines.
Be aware: this also blocks automatic WordPress core updates. If you enable this, you need another mechanism for keeping WordPress, plugins, and themes updated. WP-CLI handles this well:
wp core update
wp plugin update --all
wp theme update --all
FORCE_SSL_ADMIN
define( 'FORCE_SSL_ADMIN', true );
Forces the WordPress admin area and login page to use HTTPS. In 2026, your entire site should be on HTTPS already, but this constant is a safety net — even if someone accesses http://yoursite.com/wp-admin, they get redirected to the secure version. Login credentials never travel unencrypted.
Authentication Keys and Salts
define( 'AUTH_KEY', 'put-your-unique-phrase-here' );
define( 'SECURE_AUTH_KEY', 'put-your-unique-phrase-here' );
define( 'LOGGED_IN_KEY', 'put-your-unique-phrase-here' );
define( 'NONCE_KEY', 'put-your-unique-phrase-here' );
define( 'AUTH_SALT', 'put-your-unique-phrase-here' );
define( 'SECURE_AUTH_SALT', 'put-your-unique-phrase-here' );
define( 'LOGGED_IN_SALT', 'put-your-unique-phrase-here' );
define( 'NONCE_SALT', 'put-your-unique-phrase-here' );
These eight constants add randomness to the hashing of passwords and authentication cookies. Each one should be a long, random, unique string. WordPress provides a generator:
https://api.wordpress.org/secret-key/1.1/salt/
Or via WP-CLI:
wp config shuffle-salts
If you ever suspect your site has been compromised, changing these salts immediately invalidates all existing login cookies, forcing every user (including any attacker who's logged in) to re-authenticate.
COOKIE_DOMAIN
define( 'COOKIE_DOMAIN', 'example.com' );
Sets the domain for WordPress cookies. Useful in multisite or when you want cookies to work across subdomains. Setting it to .example.com (with the leading dot) makes cookies available to all subdomains.
WP_HTTP_BLOCK_EXTERNAL
define( 'WP_HTTP_BLOCK_EXTERNAL', true );
define( 'WP_ACCESSIBLE_HOSTS', 'api.wordpress.org,downloads.wordpress.org' );
Blocks all outgoing HTTP requests from WordPress except to the hosts you explicitly allow. This is a strong security measure for sites that don't need to communicate with external services. The WP_ACCESSIBLE_HOSTS constant whitelists specific domains — you'll almost always want api.wordpress.org for updates and security checks.
Performance Constants
WP_MEMORY_LIMIT
define( 'WP_MEMORY_LIMIT', '256M' );
Sets the maximum memory PHP can use during a frontend WordPress request. The default is 40MB for single sites and 64MB for multisite. For any site with WooCommerce, page builders, or more than a dozen plugins, 256MB is a reasonable setting.
This is NOT the same as PHP's own memory_limit in php.ini. WordPress uses WP_MEMORY_LIMIT to call ini_set('memory_limit') during bootstrap. If PHP's memory_limit is lower than WP_MEMORY_LIMIT, WordPress will try to increase it. If your host has set a hard limit via PHP-FPM, WordPress can't exceed it regardless of what you put here.
WP_MAX_MEMORY_LIMIT
define( 'WP_MAX_MEMORY_LIMIT', '512M' );
The memory limit for WordPress admin pages. Admin operations like plugin updates, media uploads, and database exports need more memory than frontend page rendering. The default is 256MB. If you're seeing "Allowed memory size exhausted" errors in the admin, increase this.
DISABLE_WP_CRON
define( 'DISABLE_WP_CRON', true );
Disables WordPress's built-in pseudo-cron system. By default, WordPress checks for scheduled tasks on every page load by spawning an asynchronous request to wp-cron.php. On low-traffic sites, tasks might not run often enough. On high-traffic sites, you're wasting resources checking the schedule on every request.
The better approach is a real server cron job:
# Run WordPress cron every 5 minutes via system cron
*/5 * * * * cd /var/www/html && wp cron event run --due-now --quiet
Or if WP-CLI isn't available:
*/5 * * * * wget -q -O - https://yoursite.com/wp-cron.php?doing_wp_cron >/dev/null 2>&1
WP_POST_REVISIONS
define( 'WP_POST_REVISIONS', 5 );
Limits the number of post revisions WordPress stores. By default, WordPress keeps every revision indefinitely. On a site that's been running for three years with active editors, I've seen wp_posts tables with 200,000+ revision rows. Each revision is a full copy of the post content in the database.
Set this to a reasonable number. 5 gives you enough history to undo mistakes without bloating the database. Set it to false to disable revisions entirely (I wouldn't — they've saved me too many times).
AUTOSAVE_INTERVAL
define( 'AUTOSAVE_INTERVAL', 120 );
How often (in seconds) WordPress autosaves posts while you're editing. The default is 60 seconds. Each autosave fires an AJAX request that triggers a partial WordPress bootstrap. If you have multiple editors working simultaneously, that's a lot of background requests. Setting it to 120 or 180 seconds reduces server load without meaningfully increasing the risk of lost work.
EMPTY_TRASH_DAYS
define( 'EMPTY_TRASH_DAYS', 14 );
Number of days before trashed posts are permanently deleted. Default is 30. Set to 0 to disable trash entirely (items delete immediately — not recommended). I usually set this to 14 days to keep the database cleaner.
WP_CACHE
define( 'WP_CACHE', true );
Enables the advanced caching mechanism. When true, WordPress looks for wp-content/advanced-cache.php and loads it early in the bootstrap process. This is how page caching plugins like WP Rocket and WP Super Cache hook in — they drop their caching logic into advanced-cache.php and rely on this constant being true.
You usually don't set this manually. Caching plugins add it automatically during activation. But if you're debugging caching issues and want to temporarily disable the page cache without deactivating the plugin, setting this to false does the trick.
Compression Constants
define( 'COMPRESS_CSS', true );
define( 'COMPRESS_SCRIPTS', true );
define( 'ENFORCE_GZIP', true );
These enable gzip compression for CSS and JavaScript served through WordPress's built-in script loader (load-scripts.php and load-styles.php). These primarily affect the admin dashboard, since frontend assets are usually handled by your web server's gzip configuration or a caching plugin.
Content and URL Constants
WP_SITEURL and WP_HOME
define( 'WP_SITEURL', 'https://example.com' );
define( 'WP_HOME', 'https://example.com' );
Hardcodes the WordPress address and site address instead of pulling them from the wp_options table. This is useful in two scenarios:
Migration recovery. If you've moved your site to a new domain and can't access the admin because the URLs in the database still point to the old domain, setting these constants overrides the database values and lets you log in.
Performance. Every WordPress request queries
wp_optionsforsiteurlandhome. Hardcoding them inwp-config.phpskips those queries. It's a micro-optimization, but on high-traffic sites, every query matters.
Important: WP_SITEURL is where WordPress core files live. WP_HOME is the URL visitors type to reach your site. They're often the same, but they can differ if you've installed WordPress in a subdirectory.
WP_CONTENT_DIR and WP_CONTENT_URL
define( 'WP_CONTENT_DIR', '/var/www/html/content' );
define( 'WP_CONTENT_URL', 'https://example.com/content' );
Moves the wp-content directory to a custom location. Some security guides recommend this because it breaks automated attacks that assume default WordPress paths. It also allows you to keep WordPress core files separate from your custom content for cleaner upgrades.
WP_DEFAULT_THEME
define( 'WP_DEFAULT_THEME', 'flavor' );
Sets the fallback theme. If the active theme breaks, WordPress falls back to this. By default it's one of the Twenty-* themes. On client sites, I set this to a known-good theme that's always installed.
Database Constants
DB_CHARSET
define( 'DB_CHARSET', 'utf8mb4' );
Sets the character set for the database. utf8mb4 is the correct setting for any modern WordPress installation — it supports the full range of Unicode characters including emoji. If you see utf8 here on an older site, consider migrating to utf8mb4. The utf8 charset in MySQL only supports 3-byte characters, which means it silently truncates emoji and some Asian characters.
DB_COLLATE
define( 'DB_COLLATE', '' );
The database collation (sorting rules). Leave this empty unless you have a specific reason to set it — WordPress will pick the best available collation for your character set (typically utf8mb4_unicode_520_ci). Setting this incorrectly can cause comparison and sorting issues across different languages.
Custom Table Prefix
$table_prefix = 'wp_';
Note this is a variable assignment ($table_prefix), not a define() constant. It sets the prefix for all WordPress database tables. Changing it from the default wp_ is a minor security measure — it prevents SQL injection attacks that assume default table names. But if you're changing this on an existing site, you need to rename every table in the database to match. It's primarily useful during initial installation.
Common Mistakes That Break Sites
I've fixed hundreds of white-screened WordPress sites over the years. These are the mistakes I see again and again.
1. Putting Constants Below "That's All, Stop Editing!"
This is the most common mistake. Someone adds a constant at the bottom of wp-config.php, below require_once ABSPATH . 'wp-settings.php';. The constant gets defined after WordPress has already loaded. Depending on the constant, it either does nothing (WordPress already used its default value) or causes a redefinition warning.
The fix: Always add custom constants between the salts section and the /* That's all, stop editing! */ comment.
2. Missing Semicolons
// This kills the site
define( 'WP_DEBUG', true )
// This works
define( 'WP_DEBUG', true );
A missing semicolon at the end of a define() call causes a PHP parse error. Because wp-config.php loads before WordPress's error handling, there's no graceful fallback. The site outputs a white screen or a raw PHP error.
3. Unclosed Quotes
// This kills the site
define( 'WP_SITEURL', 'https://example.com );
// This works
define( 'WP_SITEURL', 'https://example.com' );
A missing closing quote causes PHP to consume everything until it finds a matching quote — which might be on a completely different line, causing cascading errors that are hard to diagnose.
4. Smart Quotes from Copy-Paste
// These curly quotes kill the site (copied from WordPress blogs or Word docs)
define( 'WP_DEBUG', true );
// These straight quotes work
define( 'WP_DEBUG', true );
This one is infuriating because it's invisible at a glance. If you copy code from a blog post, WordPress itself sometimes converts straight quotes to curly quotes for typography. Paste that into wp-config.php and PHP doesn't recognize them as valid string delimiters.
Always type constants by hand, or paste into a code editor (VS Code, Sublime) that will flag invalid characters. Never paste PHP code from a CMS-rendered blog post directly into a config file.
5. Redefining an Existing Constant
define( 'WP_DEBUG', true );
// ... 50 lines later ...
define( 'WP_DEBUG', false ); // PHP notice: constant already defined
In PHP 7.x, redefining a constant throws a notice. In PHP 8.x+, it throws a warning. Either way, the second define() is silently ignored — the first value wins. On a long wp-config.php with many edits over the years, it's easy to add a duplicate without noticing.
Search your file before adding anything: does this constant already exist?
6. Wrong Value Types
// Wrong — string 'true' is NOT boolean true
define( 'WP_DEBUG', 'true' );
// Correct — boolean true, no quotes
define( 'WP_DEBUG', true );
// Wrong — string '5' works but is sloppy
define( 'WP_POST_REVISIONS', '5' );
// Correct — integer 5
define( 'WP_POST_REVISIONS', 5 );
PHP is loosely typed enough that string 'true' evaluates as truthy, so this usually works by accident. But 'false' does NOT evaluate as falsy — the string 'false' is truthy because it's a non-empty string. define( 'WP_DEBUG', 'false' ); actually ENABLES debug mode. I've seen this exact mistake cause a production site to suddenly start displaying PHP notices to visitors.
7. Editing the Wrong wp-config.php
If you have a multisite setup, a staging site in a subdirectory, or multiple WordPress installations on the same server, it's surprisingly easy to edit the wrong wp-config.php. I once spent 20 minutes debugging why my changes weren't taking effect before realizing I was editing the staging config while looking at the production site.
Always verify your working directory:
pwd
# Make sure you're in the right WordPress root
# Double-check by looking at the database name
grep DB_NAME wp-config.php
Version Control and Environment-Specific Configs
If your WordPress site is in version control (and it should be), wp-config.php presents a problem. It contains database credentials, security keys, and environment-specific settings that shouldn't be committed to a repository.
The .gitignore Approach
The simplest approach: add wp-config.php to .gitignore and manage it manually on each environment.
# .gitignore
wp-config.php
This works but means you have no version history for config changes, and you have to remember to create the file on new environments.
The Environment Variables Approach
A better approach is to read sensitive values from environment variables:
define( 'DB_NAME', getenv( 'WP_DB_NAME' ) );
define( 'DB_USER', getenv( 'WP_DB_USER' ) );
define( 'DB_PASSWORD', getenv( 'WP_DB_PASSWORD' ) );
define( 'DB_HOST', getenv( 'WP_DB_HOST' ) ?: 'localhost' );
define( 'WP_DEBUG', getenv( 'WP_DEBUG' ) === 'true' );
Set the environment variables in your server config, .env file (loaded by a library like vlucas/phpdotenv), or Docker compose file. The wp-config.php itself becomes safe to commit because it contains no secrets.
The Local Config Approach
Another pattern I use frequently: keep a version-controlled wp-config.php that includes an environment-specific override file:
// At the top of wp-config.php, before any define() calls
if ( file_exists( __DIR__ . '/wp-config-local.php' ) ) {
require_once __DIR__ . '/wp-config-local.php';
}
Then in .gitignore:
wp-config-local.php
Each developer creates their own wp-config-local.php with local database credentials and debug settings. The main wp-config.php checks if each constant is already defined before defining its defaults:
if ( ! defined( 'DB_NAME' ) ) {
define( 'DB_NAME', 'production_db' );
}
if ( ! defined( 'WP_DEBUG' ) ) {
define( 'WP_DEBUG', false );
}
This gives you the best of both worlds: a version-controlled config with environment-specific overrides.
GUI Alternatives to Hand-Editing
If all of the above sounds like a lot of ways to accidentally break your site, that's because it is. There are tools that add a safety layer between you and the raw PHP file.
WP-CLI is the command-line alternative. Instead of opening the file in a text editor, you can read and write constants programmatically:
# Read a constant
wp config get WP_DEBUG
# Set a constant
wp config set WP_DEBUG true --raw
# Set a string constant
wp config set WP_SITEURL 'https://example.com'
# List all constants
wp config list
The --raw flag tells WP-CLI to write the value as a raw PHP expression (so true becomes boolean true, not the string 'true'). Without --raw, WP-CLI wraps values in quotes. This matters for boolean and integer constants. For more WP-CLI techniques, see the WP-CLI commands every developer should know.
GUI plugins exist that let you manage wp-config.php from the WordPress admin. WP Multitool's Config Manager is one — it reads your current constants, lets you edit them from a form interface, validates syntax before writing, and creates a timestamped backup before every change. There are others, like WP Config File Editor and WPCode.
The advantage of any GUI approach is the same: you can't introduce a syntax error by mistyping a semicolon, and you always have a backup to restore if something goes wrong. The tradeoff is that you need a working WordPress installation to use them — if your site is already white-screened because of a bad config edit, the GUI can't help you. That's when you need SSH or FTP.
Recovery: When a Bad Edit Breaks Your Site
It happens. You edited wp-config.php, saved the file, and the site is showing a white screen or a PHP error. Here's the recovery process.
Step 1: Don't Panic, Get Access
You need file-level access to the server. This means SSH, SFTP, or your hosting provider's file manager. You cannot fix this from the WordPress admin because WordPress isn't loading.
ssh user@server
cd /var/www/html # or wherever your WordPress root is
Step 2: Look at the Error
If the white screen shows nothing, check the PHP error log:
# Common error log locations
tail -20 /var/log/php-fpm/error.log
tail -20 /var/log/apache2/error.log
tail -20 /var/log/nginx/error.log
# Or check PHP's configured error log
php -i | grep error_log
The error message will tell you exactly what's wrong and which line number. Something like:
PHP Parse error: syntax error, unexpected end of file in /var/www/html/wp-config.php on line 47
Step 3: Fix or Restore
If you know what you changed, fix the syntax error directly. If you're not sure what you changed or the file is a mess, restore from backup:
# If you had a backup
cp wp-config.php.bak wp-config.php
# If your caching plugin or config manager made a backup
ls wp-content/wp-config-backup*
# If you're using version control
git checkout wp-config.php
If you have no backup at all, you can recreate wp-config.php from wp-config-sample.php:
cp wp-config-sample.php wp-config.php
Then fill in your database credentials. If you don't remember them, check your hosting control panel, or look at the last known good backup in your hosting provider's system.
Step 4: Verify
# Quick syntax check without running the file
php -l wp-config.php
# Should output: No syntax errors detected
# Then load the site
curl -o /dev/null -s -w "HTTP: %{http_code}\n" https://yoursite.com
# Should output: HTTP: 200
The php -l command is a linter — it checks for syntax errors without executing the file. Run this after every wp-config.php edit to catch problems before they go live. If you're editing remotely over SSH, make it a habit:
vim wp-config.php
# make your changes, save
php -l wp-config.php
# if clean, you're good. if error, fix it
For a more detailed guide on diagnosing and recovering from site outages, see WordPress site down: what to do.
My Production wp-config.php Template
Here's the set of constants I add to every production WordPress site. Not all of them are necessary for every project, but this is my baseline:
/** Performance */
define( 'WP_MEMORY_LIMIT', '256M' );
define( 'WP_MAX_MEMORY_LIMIT', '512M' );
define( 'WP_POST_REVISIONS', 5 );
define( 'AUTOSAVE_INTERVAL', 120 );
define( 'EMPTY_TRASH_DAYS', 14 );
define( 'DISABLE_WP_CRON', true );
/** Security */
define( 'DISALLOW_FILE_EDIT', true );
define( 'FORCE_SSL_ADMIN', true );
/** Debugging (off for production) */
define( 'WP_DEBUG', false );
define( 'WP_DEBUG_LOG', false );
define( 'WP_DEBUG_DISPLAY', false );
And for staging/development:
/** Performance — relaxed for dev */
define( 'WP_MEMORY_LIMIT', '512M' );
define( 'WP_MAX_MEMORY_LIMIT', '512M' );
define( 'WP_POST_REVISIONS', 10 );
define( 'AUTOSAVE_INTERVAL', 60 );
/** Security — relaxed for dev */
define( 'DISALLOW_FILE_EDIT', false );
/** Debugging — full visibility */
define( 'WP_DEBUG', true );
define( 'WP_DEBUG_LOG', true );
define( 'WP_DEBUG_DISPLAY', true );
define( 'SCRIPT_DEBUG', true );
define( 'SAVEQUERIES', true );
The difference between environments is just a handful of boolean flags and numbers. But those flags control whether your site exposes error details to visitors, allows file modifications from the admin, or stores unlimited post revisions until the database bloats.
The Real Problem with Hand-Editing wp-config.php
I started this article by calling wp-config.php the most dangerous file in WordPress. That's not because the constants are complex. They're actually trivial — key-value pairs, booleans, and integers.
The danger is the workflow. SSH into a production server, open a critical file in a text editor, type PHP code by hand, save, and hope for the best. No syntax validation. No automatic backup. No undo button.
For a file that controls database access, security policies, and debug behavior, that workflow belongs in 2006, not 2026.
Whether you use WP-CLI, a config management plugin, environment variables, or a deployment pipeline — anything that adds validation and backups between your intention and the raw file is an improvement. The specific tool matters less than having a safety net at all.
And if you do edit it by hand — because sometimes you need to, because the site is down and you're in SSH at midnight — run php -l wp-config.php before you close the terminal. It takes one second and it's the difference between going back to sleep and getting another phone call.
If your site is already sluggish and you're not sure whether it's a config issue or something deeper, the free scan checks your backend performance — autoload size, query health, PHP environment — in about 30 seconds.





Top comments (0)