Skip to content
  • CS-06
  • Reference
  • Last checked November 7, 2026

wp-config.php Constants Reference: Defaults, Examples and Risks

Every wp-config.php constant that matters in an emergency or a tune-up: debugging, URLs, memory, cron, security, updates, database and multisite, each with its default, an example and the risk.

Run the health check

wp-config.php is the file WordPress reads before anything else. It holds the database login, the security keys and dozens of optional constants that change how WordPress behaves. Many emergency fixes are one line here: turning on error logging, forcing the right site URL, raising memory or stopping a broken cron. This reference lists each constant with its default, an example, when to use it and what can go wrong. Defaults were checked against the WordPress core source (version 7.1); older versions may differ where noted.

Placeholders: DOMAIN is your site’s host name (for example example.com). SITEUSER is the system account that owns the site files. EMAIL is an address you read. Values shown in examples such as 256M are illustrations, not recommendations for every site.

Where constants go

Rule Why
Add custom constants above the line /* That's all, stop editing! Happy publishing. */. Current sample files also mark the start of the spot with /* Add any custom values between this line and the "stop editing" line. */ Everything below that line loads wp-settings.php, which defines defaults for any constant not yet set. A constant defined after that point is ignored (and PHP 8 warns that it is already defined).
Define each constant once. A second define() of the same name is ignored with a warning. Search the file before adding a line.
Booleans and numbers are not quoted. define( 'WP_DEBUG', true ); not 'true'. The string 'false' is truthy in PHP.
The file may live one folder above the WordPress root. WordPress checks there if it is not in the root. Edit the copy that is actually loaded (wp config path tells you).
Keep permissions tight. Typically 640 or 600 where the server allows it, owned by SITEUSER. Never world-writable.
Edit with WP-CLI when you can. wp config set WP_DEBUG true --raw places the line correctly and avoids syntax errors. A typo in this file takes the whole site down.

Debugging

Constant Default Example When to use Risk
WP_DEBUG false (current versions default to true when WP_ENVIRONMENT_TYPE is development or WP_DEVELOPMENT_MODE is set) define( 'WP_DEBUG', true ); Turns on PHP notices, warnings and deprecation messages. The master switch for the two below. On its own it also displays errors, because WP_DEBUG_DISPLAY defaults to true. Pair with the next two on live sites.
WP_DEBUG_LOG false define( 'WP_DEBUG_LOG', true ); or define( 'WP_DEBUG_LOG', '/home/SITEUSER/logs/wp-errors.log' ); Writes errors to wp-content/debug.log, or to a custom path (WordPress 5.1 and later). Only works when WP_DEBUG is true. The default wp-content/debug.log can be downloaded by anyone who guesses the URL and may reveal paths and data. Use a path outside the web root and turn logging off when done.
WP_DEBUG_DISPLAY true define( 'WP_DEBUG_DISPLAY', false ); Hides errors from visitors while still logging them. Add @ini_set( 'display_errors', 0 ); for belt and braces. Leaving it true on a live site shows file paths to visitors and can break AJAX and REST responses.
SCRIPT_DEBUG false (true only on development builds of core) define( 'SCRIPT_DEBUG', true ); Loads the non-minified versions of core JavaScript and CSS, for tracing script errors in the block editor or admin. Larger files, slower admin. Turn off afterward.
SAVEQUERIES Not defined (off) define( 'SAVEQUERIES', true ); Stores every database query, its time and the calling function in $wpdb->queries. Used by Query Monitor-style analysis. Uses memory and slows every request. Never leave on in production.
WP_ENVIRONMENT_TYPE production define( 'WP_ENVIRONMENT_TYPE', 'staging' ); Tells WordPress, plugins and themes what kind of site this is. Allowed values: local, development, staging, production. Can also be set as a server environment variable. A copied staging config on a live site can switch on debug behavior or disable things plugins only want off in staging.
WP_DEVELOPMENT_MODE '' (off) define( 'WP_DEVELOPMENT_MODE', 'theme' ); WordPress 6.3 and later. Values core, plugin, theme or all. Disables some caching that gets in the way of active development. Slower on a live site. Leave empty in production.
WP_DISABLE_FATAL_ERROR_HANDLER Not defined (handler on) define( 'WP_DISABLE_FATAL_ERROR_HANDLER', true ); Turns off the “There has been a critical error on this website” handler and recovery mode, so raw PHP errors show (if display is on). Useful on development copies. Removes recovery mode emails and the safe admin link on live sites.
RECOVERY_MODE_EMAIL The site’s admin email setting define( 'RECOVERY_MODE_EMAIL', 'EMAIL' ); Sends fatal error recovery links to a different address, such as the developer’s. If this inbox is unread, nobody sees the recovery link.

URLs and paths

Constant Default Example When to use Risk
WP_HOME Not defined; the home option is used define( 'WP_HOME', 'https://DOMAIN' ); Forces the public site address. The emergency fix when a wrong URL in the database causes redirects to an old domain or HTTP. Overrides Settings, General, which then shows the field grayed out. No trailing slash.
WP_SITEURL Not defined; the siteurl option is used define( 'WP_SITEURL', 'https://DOMAIN' ); Forces the address where WordPress core files live. Differs from WP_HOME only when WordPress is in a subfolder (https://DOMAIN/wp). A wrong value breaks the admin and login. No trailing slash.
WP_CONTENT_DIR ABSPATH . 'wp-content' define( 'WP_CONTENT_DIR', __DIR__ . '/content' ); Moves the content folder. Full server path, no trailing slash. Plugins that hard-code wp-content break. Must be set together with the URL below.
WP_CONTENT_URL Site URL plus /wp-content define( 'WP_CONTENT_URL', 'https://DOMAIN/content' ); Public URL of the moved content folder. Also used to serve content from a different host. An http:// value causes mixed content warnings on an HTTPS site.
WP_PLUGIN_DIR / WP_PLUGIN_URL WP_CONTENT_DIR . '/plugins' / WP_CONTENT_URL . '/plugins' define( 'WP_PLUGIN_DIR', WP_CONTENT_DIR . '/plugins' ); Moves the plugins folder only. Same as above.
UPLOADS Not defined (wp-content/uploads) define( 'UPLOADS', 'media' ); Path to uploads, relative to the WordPress root, no leading slash. Existing attachment URLs in posts do not move with it.
COOKIE_DOMAIN '' (current host) define( 'COOKIE_DOMAIN', 'DOMAIN' ); Sets the domain for login cookies. Occasionally needed for multisite domain setups. A wrong value causes login loops: you log in and land back on the login page.

Performance and housekeeping

Constant Default Example When to use Risk
WP_MEMORY_LIMIT 40M single site, 64M multisite (or the PHP limit if WordPress cannot change it) define( 'WP_MEMORY_LIMIT', '256M' ); Memory for front-end requests. Raise it for “Allowed memory size exhausted” errors on the front end. WordPress only ever raises PHP’s memory_limit; it cannot exceed a hard limit set by the host. A high value can hide a leaking plugin.
WP_MAX_MEMORY_LIMIT 256M (or higher if PHP’s limit is already higher) define( 'WP_MAX_MEMORY_LIMIT', '512M' ); Memory for admin screens and heavy tasks such as image processing. Raise for memory errors in wp-admin or during uploads. Same host ceiling applies.
WP_POST_REVISIONS true (unlimited) define( 'WP_POST_REVISIONS', 10 ); Limits stored revisions per post. false or 0 turns revisions off. Does not delete existing revisions. Turning them off removes the undo history editors rely on.
AUTOSAVE_INTERVAL 60 seconds define( 'AUTOSAVE_INTERVAL', 120 ); How often the editor autosaves. Raise it to reduce admin-ajax or REST load on busy editorial sites. More work lost if a browser crashes.
EMPTY_TRASH_DAYS 30 define( 'EMPTY_TRASH_DAYS', 7 ); Days before trashed posts, pages and comments are permanently deleted. 0 disables the trash entirely: delete becomes permanent with no undo.
MEDIA_TRASH false define( 'MEDIA_TRASH', true ); Adds a trash for media items instead of immediate deletion. Trashed files still use disk space until emptied.
WP_CACHE false define( 'WP_CACHE', true ); Loads the wp-content/advanced-cache.php drop-in used by page cache plugins. Usually written by the plugin. Left on after removing a cache plugin, a stale advanced-cache.php can serve old pages or fatal. Remove both together.
DISABLE_WP_CRON Not defined (WP-Cron runs on page loads) define( 'DISABLE_WP_CRON', true ); Stops WP-Cron from spawning on visits. Use with a real system cron job running wp cron event run --due-now every few minutes. Without a replacement cron job, scheduled posts, backups, emails and updates silently stop.
ALTERNATE_WP_CRON Not defined (off) define( 'ALTERNATE_WP_CRON', true ); Runs cron by redirecting the visitor’s request instead of a loopback request. Last resort when loopback requests are blocked and system cron is not available. Adds ?doing_wp_cron to URLs visitors see and can interfere with caching and forms. Prefer system cron.
WP_CRON_LOCK_TIMEOUT 60 seconds define( 'WP_CRON_LOCK_TIMEOUT', 120 ); Minimum time between cron runs, preventing overlapping runs. Too low lets long jobs overlap; too high delays events.
CONCATENATE_SCRIPTS true in the admin define( 'CONCATENATE_SCRIPTS', false ); Stops WordPress joining admin scripts into one load-scripts.php request. A classic fix when admin buttons, menus or the editor stop working behind some proxies or security rules. More HTTP requests in the admin. Mostly a diagnostic.
IMAGE_EDIT_OVERWRITE Not defined (off) define( 'IMAGE_EDIT_OVERWRITE', true ); When editing images in the media editor, overwrites the previously edited files instead of keeping each set of edits. The original is still kept for “Restore”. Earlier edited versions are lost.

Security

Constant Default Example When to use Risk
DISALLOW_FILE_EDIT Not defined (editor available) define( 'DISALLOW_FILE_EDIT', true ); Removes the plugin and theme file editors from the admin. Recommended on every live site, because a stolen admin login can otherwise inject PHP in seconds. Almost none. Edit code over SFTP or Git instead.
DISALLOW_FILE_MODS Not defined (allowed) define( 'DISALLOW_FILE_MODS', true ); Blocks installing, updating and deleting plugins and themes from the admin, the file editor, and automatic updates. For sites deployed from version control. Security updates stop arriving unless your deployment process applies them. Never set it and walk away.
FORCE_SSL_ADMIN true when the siteurl option starts with https (current versions), otherwise false define( 'FORCE_SSL_ADMIN', true ); Forces logins and the admin over HTTPS. Behind a proxy that terminates TLS without telling WordPress, this causes a redirect loop. See the reverse proxy recipe.
Keys and salts: AUTH_KEY, SECURE_AUTH_KEY, LOGGED_IN_KEY, NONCE_KEY, AUTH_SALT, SECURE_AUTH_SALT, LOGGED_IN_SALT, NONCE_SALT Unique random strings set at install wp config shuffle-salts Sign login cookies and nonces. Replace all eight after a compromise or when someone with access leaves. WordPress.org also serves fresh values at https://api.wordpress.org/secret-key/1.1/salt/. Changing them logs every user out, which is the point. Never publish them or reuse them between sites.
WP_HTTP_BLOCK_EXTERNAL Not defined (outbound allowed) define( 'WP_HTTP_BLOCK_EXTERNAL', true ); Blocks outbound requests made through the WordPress HTTP API, except to the site itself and localhost. Hardening for locked-down sites, or to stop a plugin calling home. Breaks updates, license checks, payment gateways and embeds unless allowed below.
WP_ACCESSIBLE_HOSTS Not defined define( 'WP_ACCESSIBLE_HOSTS', 'api.wordpress.org,downloads.wordpress.org,*.stripe.com' ); Comma-separated allow list used with WP_HTTP_BLOCK_EXTERNAL. Wildcards such as *.example.com are supported. Only covers code that uses the WordPress HTTP API; direct cURL calls bypass it.
DISALLOW_UNFILTERED_HTML Not defined define( 'DISALLOW_UNFILTERED_HTML', true ); Removes the unfiltered_html capability from everyone, including administrators, so script tags and other unsafe HTML are stripped from content. Breaks legitimate embeds and tracking snippets pasted into content.
ALLOW_UNFILTERED_UPLOADS Not defined define( 'ALLOW_UNFILTERED_UPLOADS', true ); Lets administrators upload any file type. Listed so you recognize it. Dangerous: allows uploading executable or script files. Remove after a one-off use.

Updates and filesystem access

Constant Default Example When to use Risk
AUTOMATIC_UPDATER_DISABLED Not defined (auto-updates allowed) define( 'AUTOMATIC_UPDATER_DISABLED', true ); Turns off all background updates: core, plugins, themes and translations. For sites where updates are applied by a managed process. Security releases are no longer applied automatically.
WP_AUTO_UPDATE_CORE Not defined: minor and security releases on; major releases follow the setting on Dashboard, Updates define( 'WP_AUTO_UPDATE_CORE', 'minor' ); Values: true (all core updates), 'minor' (minor and security only), false (none). Core also accepts 'beta', 'rc', 'development' and 'branch-development', which behave like true for update decisions. false leaves known vulnerabilities unpatched. Overrides the admin setting.
FS_METHOD Auto-detected define( 'FS_METHOD', 'direct' ); How WordPress writes files during installs and updates: direct, ssh2, ftpext or ftpsockets. Setting direct stops the “Connection Information” FTP prompt when PHP runs as the file owner. Forcing direct when PHP runs as a different user than the file owner creates files owned by the web server, or fails. Fix ownership instead where possible.
FTP_HOST, FTP_USER, FTP_PASS, FTP_SSL Not defined define( 'FTP_HOST', 'ftp.DOMAIN:21' ); Stored credentials for the ftpext and ftpsockets methods. FTP_SSL true uses FTPS. Credentials in plain text in a PHP file. Prefer direct or SSH keys.
FTP_PUBKEY, FTP_PRIKEY Not defined define( 'FTP_PRIKEY', '/home/SITEUSER/.ssh/id_rsa' ); Key paths for the ssh2 method (needs the PHP ssh2 extension). The key must be unreadable by other accounts.
FTP_BASE, FTP_CONTENT_DIR, FTP_PLUGIN_DIR Auto-detected define( 'FTP_BASE', '/public_html/' ); Paths as the FTP account sees them, when auto-detection fails. Wrong paths make updates fail with “could not find directory”.
FS_CHMOD_DIR / FS_CHMOD_FILE Based on existing permissions, normally 0755 and 0644 define( 'FS_CHMOD_FILE', 0644 ); Permissions applied to files and folders WordPress creates. Octal, no quotes. 0777 or 0666 lets other accounts on the server modify your site.

Database

Constant Default Example When to use Risk
DB_NAME, DB_USER, DB_PASSWORD Set at install define( 'DB_NAME', 'DATABASE_NAME' ); Database login. The first check for “Error establishing a database connection”. Watch for stray spaces and unescaped single quotes in passwords.
DB_HOST localhost in the sample file 'localhost', '127.0.0.1', 'db.example.net:3307', 'localhost:/var/run/mysqld/mysqld.sock', '[::1]:3306' Host name or IP, optionally with :PORT, a Unix socket path after :, or an IPv6 address in brackets. localhost uses a socket while 127.0.0.1 uses TCP; database permissions can differ between the two, so one may work when the other fails.
DB_CHARSET utf8mb4 in the sample file define( 'DB_CHARSET', 'utf8mb4' ); Character set for the connection. utf8mb4 supports emoji and all of Unicode. Changing it on an existing site does not convert stored data and can garble text.
DB_COLLATE '' define( 'DB_COLLATE', '' ); Collation. Empty lets the database pick the default for the charset, which is right for almost everyone. A collation not supported by the server (for example after moving to an older MySQL) causes errors on import.
$table_prefix 'wp_' $table_prefix = 'wp_a1b2_'; A variable, not a constant. Lets several installs share one database. Letters, numbers and underscores only. Changing it on a live site needs every table renamed plus prefixed rows in the options and usermeta tables (PREFIX_user_roles, PREFIX_capabilities, PREFIX_user_level), or nobody can log in.
WP_ALLOW_REPAIR Not defined define( 'WP_ALLOW_REPAIR', true ); Enables the repair page at https://DOMAIN/wp-admin/maint/repair.php for crashed or corrupted tables. The page works without logging in. Remove the line as soon as you finish.
CUSTOM_USER_TABLE / CUSTOM_USER_META_TABLE Not defined define( 'CUSTOM_USER_TABLE', 'shared_users' ); Points WordPress at a different users table, to share logins between installs in one database. Set before install. Roles are still stored per site; users may exist with no capabilities. Complex to undo.

Multisite

Constant Default Example When to use Risk
WP_ALLOW_MULTISITE Not defined define( 'WP_ALLOW_MULTISITE', true ); Unlocks Tools, Network Setup, the first step in creating a network. WordPress then gives you the lines below to add. Harmless on its own. Converting a site to a network is hard to reverse.
MULTISITE Not defined define( 'MULTISITE', true ); Switches the install into network mode. Removing it on an existing network breaks every subsite.
SUBDOMAIN_INSTALL Set during network setup define( 'SUBDOMAIN_INSTALL', false ); true for site.DOMAIN, false for DOMAIN/site/. Cannot simply be flipped later; URLs throughout the database depend on it. Subdomain networks need wildcard DNS and a certificate that covers the subdomains.
DOMAIN_CURRENT_SITE Set during network setup define( 'DOMAIN_CURRENT_SITE', 'DOMAIN' ); The network’s main domain. When moving a network, the domain also has to change in the site, blogs and sitemeta tables, or you get redirect loops and “Error establishing a database connection”.
PATH_CURRENT_SITE Set during network setup define( 'PATH_CURRENT_SITE', '/' ); Path of the main site, usually /. Must match the path stored in the database.
SITE_ID_CURRENT_SITE / BLOG_ID_CURRENT_SITE 1 define( 'BLOG_ID_CURRENT_SITE', 1 ); IDs of the network and its main site. Rarely changed.
NOBLOGREDIRECT Not defined define( 'NOBLOGREDIRECT', 'https://DOMAIN/' ); Where visitors go when they request a subsite that does not exist. On subdirectory networks it can also redirect genuine 404s, which confuses search engines.
WP_DEFAULT_THEME twentytwentyfive in 7.1 (changes with each default theme) define( 'WP_DEFAULT_THEME', 'THEME_SLUG' ); Theme used for new sites and as a fallback. A slug that is not installed leaves new sites with a broken theme.

Common recipes

Safe error logging on a live site

define( 'WP_DEBUG', true );
define( 'WP_DEBUG_LOG', '/home/SITEUSER/logs/wp-errors.log' );
define( 'WP_DEBUG_DISPLAY', false );
@ini_set( 'display_errors', 0 );

Reproduce the problem, read the log, then set WP_DEBUG back to false. Create the log folder first and make sure SITEUSER can write to it.

HTTPS behind a reverse proxy, load balancer or CDN

When TLS ends at a proxy, PHP sees a plain HTTP request, so WordPress keeps redirecting to HTTPS and you get a redirect loop or mixed content. If the proxy sends X-Forwarded-Proto, tell WordPress the original request was secure. Place this above the “stop editing” line:

if ( isset( $_SERVER['HTTP_X_FORWARDED_PROTO'] ) && strpos( $_SERVER['HTTP_X_FORWARDED_PROTO'], 'https' ) !== false ) {
    $_SERVER['HTTPS'] = 'on';
}
define( 'FORCE_SSL_ADMIN', true );

Only use this when your own proxy always sets or overwrites the header; otherwise a visitor could send it themselves. With Cloudflare, prefer SSL mode Full (strict) with a valid origin certificate over Flexible, which causes this exact loop.

Locked out by a wrong site URL

define( 'WP_HOME', 'https://DOMAIN' );
define( 'WP_SITEURL', 'https://DOMAIN' );

Log in, fix Settings, General (or run wp option update home and wp option update siteurl), then remove the two lines so the setting is editable again. Replace old URLs in content with wp search-replace.

Replace WP-Cron with a real cron job

define( 'DISABLE_WP_CRON', true );
*/5 * * * * cd /PATH/TO/SITE && wp cron event run --due-now --quiet

Install the second line in SITEUSER‘s crontab (crontab -e as that user). /PATH/TO/SITE is the WordPress root.

Hardened production baseline

define( 'WP_ENVIRONMENT_TYPE', 'production' );
define( 'DISALLOW_FILE_EDIT', true );
define( 'WP_DEBUG', false );
define( 'WP_POST_REVISIONS', 20 );
define( 'FORCE_SSL_ADMIN', true );

Repair crashed tables

define( 'WP_ALLOW_REPAIR', true );

Visit https://DOMAIN/wp-admin/maint/repair.php, run “Repair Database”, then delete the line immediately. With shell access, wp db repair does the same without exposing a public page.

Memory errors

define( 'WP_MEMORY_LIMIT', '256M' );
define( 'WP_MAX_MEMORY_LIMIT', '512M' );

If the error still quotes the old limit, the host enforces a lower PHP memory_limit that WordPress cannot raise; change it in the hosting panel or PHP settings.

Gotchas

  • A white screen after editing. One missing semicolon or quote in wp-config.php is a fatal error for every page. Keep a copy before editing and check with php -l wp-config.php.
  • Curly quotes. Copying snippets from word processors or some web pages turns ' into typographic quotes, which PHP rejects. Use a plain text editor.
  • Below the line does nothing. Constants added after require_once ABSPATH . 'wp-settings.php'; arrive too late.
  • WP_DEBUG alone shows errors to the public. Because WP_DEBUG_DISPLAY defaults to true. Always set display to false on live sites.
  • Constants beat database settings. WP_HOME, WP_SITEURL and WP_AUTO_UPDATE_CORE override the admin screens, which can make settings look stuck. Check the file before chasing plugins.
  • Hosts add their own lines. Managed hosts often define constants in wp-config.php or in a file it includes. Search for require and include lines before assuming a constant is unset.
  • DISALLOW_FILE_MODS also kills auto-updates. It is easy to forget it is there months later when a plugin vulnerability is announced.
  • WP_ALLOW_REPAIR left on. The repair page needs no login. Remove the line the same day.
  • Staging configs copied to live. Check WP_ENVIRONMENT_TYPE, WP_HOME, debug settings and database credentials after every migration.
  • Secrets in backups and repositories. This file contains the database password and salts. Keep it out of public repositories and shared screenshots.

Need the full fix?

Cheat sheets are quick reference. The field guides walk you through each emergency step by step.

Open the Emergency Room

Search the field manual

What is going wrong?

Press / to search from any page, Esc to close