wp-config.php: the essential settings every WordPress owner should know

A curated reference to the wp-config.php constants that actually matter: database, URL, memory, debug, security keys, file system, cron and environment flags, with defaults, version notes and the production pitfalls the official handbook glosses over.

Scope and versions. This reference covers the wp-config.php constants you are most likely to add, change, or be asked about, for WordPress 5.5 and newer, with explicit notes where a constant only exists from a later version (WordPress 5.5 introduced WP_ENVIRONMENT_TYPE; WordPress 6.3 introduced WP_DEVELOPMENT_MODE). It is deliberately curated rather than exhaustive. The official wp-config.php reference in the Advanced Administration Handbook lists every constant WordPress recognises, and the APIs handbook documents them again from a developer angle. This article picks the subset that matters in day-to-day operation and explains what the defaults actually mean.

A quick framing before the reference sections. Every constant here is a PHP define() that has to execute before wp-settings.php runs, which is why WordPress puts the /* That's all, stop editing! Happy publishing. */ marker in the shipped file. Constants added below that line are ignored in some bootstrap scenarios, so the rule is simple: put new defines above that marker, not below.

What wp-config.php controls

wp-config.php lives in the WordPress document root (or, in hardened setups, one directory above it, which WordPress will still find automatically). It is a PHP file loaded very early in the WordPress bootstrap by wp-load.php, and its job is to set the environment that wp-settings.php then uses to initialise the rest of core. That means it controls three kinds of things:

  • Bootstrap parameters: database credentials, table prefix, site URLs, file system access method, cache inclusion. These are read before WordPress core code runs.
  • Runtime toggles: debug flags, memory limits, environment type, cron behaviour. These are read while WordPress is running and change how it behaves on every request.
  • Security constants: keys and salts used by wp_salt() to salt authentication cookies and nonces.

Because it is a plain PHP file, changes take effect on the next request. There is no service to restart, no cache to flush, no daemon to reload. This is a common misconception (covered at the end of this article), and it trips up site owners who assume wp-config.php behaves like a PHP ini file.

Database connection settings

The four database constants are what the WordPress installer writes first. They are required, and they are the only place WordPress stores credentials for MySQL or MariaDB:

Constant Type Required Description
DB_NAME string yes Name of the database WordPress connects to.
DB_USER string yes MySQL or MariaDB user with privileges on DB_NAME.
DB_PASSWORD string yes Password for DB_USER. Stored in plain text, which is why wp-config.php needs strict file permissions.
DB_HOST string yes Database host. localhost resolves via a UNIX socket on many systems; 127.0.0.1 forces TCP. Can include a port (db.example.internal:3307) or a socket path (localhost:/var/run/mysqld/mysqld.sock).
DB_CHARSET string no Character set used for the database connection. Default: utf8, but any modern install uses utf8mb4.
DB_COLLATE string no Collation. Default empty (let MySQL pick). Most installs leave this blank.
$table_prefix string yes The table prefix, set as a global variable, not a constant. Default wp_. Changing it on an existing site requires renaming every table and updating usermeta keys; it is not a post-install configuration change.

A plausibility rule: if WordPress shows Error establishing a database connection, the first thing to check is whether DB_HOST matches what your host actually exposes. Many shared hosts use a hostname other than localhost, and many managed hosts change it during a server migration without telling you.

WordPress address constants

WP_SITEURL and WP_HOME are optional overrides for the two URL values that WordPress otherwise stores in the wp_options table as siteurl and home. Setting them in wp-config.php has three practical effects:

  1. It takes the URLs out of the database, so a search-replace after a migration does not need to touch them.
  2. It locks the URLs, so an administrator cannot accidentally change them in Settings > General and log themselves out.
  3. It fixes redirect loops that can happen when the database stores a different URL than the one the browser is actually using, for example after a hasty HTTP-to-HTTPS move.
define( 'WP_HOME', 'https://yoursite.nl' );
define( 'WP_SITEURL', 'https://yoursite.nl' );

WP_HOME is the URL visitors see (the front of the site). WP_SITEURL is where WordPress core lives. In most installs they are the same. They differ only when you move WordPress core into its own subdirectory while keeping the front of the site at the root.

Do not use trailing slashes. WordPress expects the URL without one.

Memory limits

WordPress has two memory-limit constants, and they are both scoped to PHP's memory_limit, not to anything in WordPress itself. WordPress can never allocate more memory than PHP allows; these constants can only raise the ceiling up to what PHP permits.

Constant Default (single site) Default (multisite) Scope
WP_MEMORY_LIMIT 40M 64M Applies to front-end and admin requests unless overridden per request.
WP_MAX_MEMORY_LIMIT 256M 256M Applies to admin-area scripts like plugin/theme updates, media processing, and Site Health. WordPress raises the effective limit to this value when it enters the admin context.

These are documented in the APIs handbook with their exact defaults. The usual cause of Allowed memory size exhausted errors is a specific plugin overshooting the 40M front-end default, which is a pre-2010 value that makes little sense on modern servers. Raising both constants is safe if the underlying PHP memory_limit allows it; the actual hard ceiling is whichever of PHP and WordPress is lower.

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

If these values are set but the site still crashes with a memory error, the bottleneck is PHP. Check php.ini or your host's PHP settings panel.

Debug settings

Debug is where a lot of damage gets done, because the default pattern for WP_DEBUG = true is to also show errors on the front of the site. The official debug guide is explicit: "It is not recommended to use WP_DEBUG or the other debug tools on live sites; they are meant for local testing and staging installs."

Constant Default Effect when true
WP_DEBUG false Sets PHP error_reporting to E_ALL and surfaces deprecation notices. When set to true, WP_DEBUG_DISPLAY also defaults to true unless you explicitly set it to false.
WP_DEBUG_LOG false When true, writes errors to wp-content/debug.log. Since WordPress 5.1, also accepts a file path string for a custom location. The default location (wp-content/debug.log) did not change in 5.1; 5.1 only added the ability to specify a different path.
WP_DEBUG_DISPLAY true (when WP_DEBUG is on) Prints errors inline to the HTML response. Setting this to false is what makes the "log but hide" production pattern work.
SCRIPT_DEBUG false Forces WordPress to load the non-minified versions of core JS and CSS. Useful when debugging the admin UI.
SAVEQUERIES false Stores every database query of a request in $wpdb->queries for later inspection. Expensive: only turn on for a specific debugging session, never leave on.
WP_DISABLE_FATAL_ERROR_HANDLER false Turns off the Recovery Mode introduced in WordPress 5.2, so fatal errors surface normally instead of triggering the recovery workflow. Useful in a development environment where you want WP_DEBUG_DISPLAY output to reach the screen.

The safe production debug pattern is to log errors without displaying them:

define( 'WP_DEBUG', true );
define( 'WP_DEBUG_LOG', true );
define( 'WP_DEBUG_DISPLAY', false );
@ini_set( 'display_errors', '0' );

The display_errors ini override belongs alongside WP_DEBUG_DISPLAY = false, because some PHP error types slip past WordPress's output filters if PHP's own display toggle is still on. Without it, you can still leak errors to visitors.

A security note: wp-content/debug.log is writable by the PHP user and, by default, served by the web server at /wp-content/debug.log, which means anyone who can guess the path can read your errors. If you enable WP_DEBUG_LOG in production even briefly, either point it at a path outside the web root or add an .htaccess or nginx rule that denies access. The Advanced Administration Handbook flags this explicitly as a security risk.

For the related error flood from set_time_limit(), see Maximum execution time exceeded, which usually shows up once debug logging is enabled and a slow plugin starts complaining.

Security keys and salts

WordPress generates these as eight constants: four keys (AUTH_KEY, SECURE_AUTH_KEY, LOGGED_IN_KEY, NONCE_KEY) and four salts (AUTH_SALT, SECURE_AUTH_SALT, LOGGED_IN_SALT, NONCE_SALT). Their only job is to feed wp_salt(), which produces the salts used when WordPress hashes authentication cookies and nonces.

They do not encrypt anything. They do not touch the database. They are not applied to passwords at rest. This is the misconception section worth reading carefully: security keys are salts for hashes used by session cookies and CSRF nonces, full stop.

Generate them from https://api.wordpress.org/secret-key/1.1/salt/, which returns a fresh set every request. Paste the eight lines into wp-config.php, replacing any existing values.

What happens when you rotate them. All existing cookies become invalid, so every logged-in user (including you) is logged out immediately. Any in-progress form that relies on a nonce becomes invalid too. This is why you rotate keys deliberately, usually as part of incident response, not on a schedule. Snicco's "How WordPress Uses Salts and Why You Should Not Rotate Them" makes the case against scheduled rotation in detail: routine rotation has no security benefit and a real operational cost.

File system settings

When WordPress needs to write files on its own behalf (core updates, plugin installs, theme updates), it uses the WP_Filesystem API, which picks a "method" based on what is writable. Two constants control that behaviour:

Constant Default Accepted values Description
FS_METHOD (auto-detected) direct, ssh2, ftpext, ftpsockets Forces the file system method. direct tells WordPress to write files using plain PHP fopen, which only works if the PHP user owns the target files.
FS_CHMOD_DIR 0755 octal Permissions applied to directories WordPress creates.
FS_CHMOD_FILE 0644 octal Permissions applied to files WordPress creates.

The reason to set FS_METHOD explicitly is the "please enter your FTP credentials" screen. When FS_METHOD is auto-detected and the PHP user does not own the WordPress files (a common shared-hosting misconfiguration), WordPress falls back to asking for FTP credentials before every update. Setting define( 'FS_METHOD', 'direct' ); and then fixing ownership so the PHP user owns wp-content is the combination that makes the prompt go away permanently. If direct does not work because ownership genuinely cannot be changed, the prompt is warning you about a real permissions problem and hiding it is worse than leaving it.

Environment flags

These are the runtime behavioural flags that senior admins set to lock a site down or scope its behaviour for a specific environment.

Constant Introduced Default Description
DISABLE_WP_CRON pre-2.9 false Stops WordPress from triggering wp-cron.php at the end of every visitor request. When true, you must hit wp-cron.php yourself on a real schedule (usually a system cron every minute).
DISALLOW_FILE_EDIT WordPress 2.9 (not 4.9) false Hides the built-in plugin and theme file editor in wp-admin. Equivalent to stripping the edit_plugins, edit_themes and edit_files capabilities from every user (see WordPress user roles and permissions for the full capability reference).
DISALLOW_FILE_MODS present in modern WordPress false Stronger version of the previous: hides the editor and also blocks plugin/theme installation and updates from the admin. Use only on locked-down managed sites where deploys happen through version control.
WP_CACHE pre-2.9 false When true, WordPress loads wp-content/advanced-cache.php during bootstrap. Most page-cache plugins flip this on automatically during activation.
WP_ENVIRONMENT_TYPE WordPress 5.5 production Accepted values: local, development, staging, production. Returned by wp_get_environment_type() so plugins and themes can branch on environment. When set to development, WP_DEBUG auto-enables if it is not already defined. See the WordPress staging environment guide for the canonical use case.
WP_DEVELOPMENT_MODE WordPress 6.3 '' (empty) Accepted values: '', core, plugin, theme, all. Scopes development mode to a specific subsystem. Its primary current effect is bypassing the theme.json cache when set to theme, which is what theme developers need to see block style changes immediately. Theme customizations should live in a WordPress child theme to survive updates. Distinct from WP_ENVIRONMENT_TYPE: the environment type says what kind of site this is; development mode says what you are actively working on.
FORCE_SSL_ADMIN present false Forces the admin area and login to HTTPS. Most modern hosts terminate TLS at a reverse proxy, in which case this constant should be paired with trusting HTTP_X_FORWARDED_PROTO, or WordPress will enter an admin redirect loop.
COOKIE_DOMAIN present empty (host-only cookie) Controls the Domain attribute on auth cookies. Setting it explicitly is needed on multisite subdomain networks, and in rare cases where a reverse proxy rewrites the host header.
AUTOMATIC_UPDATER_DISABLED present false When true, disables all automatic background updates (core, translations, plugins, themes). Only set this if you have a real deployment pipeline replacing the functionality; otherwise it is a foot-gun.

The constant that confuses the most people is DISALLOW_FILE_EDIT. Its default has always been false (the editor is on). Setting it to true is an explicit opt-in. WordPress 4.9 did not introduce it and did not change its default; what 4.9 added was a loopback-based fatal error sandbox around the editor, which is a different feature entirely. The constant itself has existed since roughly WordPress 2.9.

How to safely edit wp-config.php

Four rules that save more sites than any configuration value.

  1. Always take a backup first. A broken wp-config.php takes the whole site down with a white screen, because every request loads it. Copy the file to wp-config.php.bak before you touch it, or use your host's file manager "duplicate" option. Restoring is a one-command fix; debugging a syntax error at 2am without a backup is not.
  2. Add new defines above the "stop editing" comment. The shipped file ends with /* That's all, stop editing! Happy publishing. */ followed by the wp-settings.php include. Anything above that line runs before WordPress loads. Anything below it runs after core is already booted, which means some constants simply stop working there.
  3. Do not paste snippets with smart quotes. Copy-pasting from blog posts often turns straight quotes (" and ') into curly quotes (" and '), which PHP rejects as a syntax error. If the site breaks after a paste, this is usually why. Retype the quotes by hand.
  4. Tighten file permissions. Because wp-config.php stores the database password in plain text, its permissions matter. The hardening guide recommends 440 or 400, owned by the user running PHP. On shared hosts you may not be able to go below 644; that is a limitation of the hosting environment, not something to fix in wp-config.php itself.

Changes take effect on the very next request. There is no PHP-FPM restart needed. The misconception that "wp-config.php changes require a PHP-FPM restart" comes from a different problem: OPcache caching stale copies of PHP files from disk when the server has opcache.validate_timestamps=0. That is a server misconfiguration, not normal WordPress behaviour, and the fix is to fix OPcache, not to restart PHP for every wp-config change.

Once wp-config.php is set up correctly, the three errors it is most commonly blamed for are worth reading in order, because each points back to a specific constant above. For the database-connection variant, start with Error establishing a database connection. For the memory variant, see Allowed memory size exhausted in WordPress. For the PHP timeout variant, see Maximum execution time exceeded.

Need a WordPress fix or custom feature?

From error fixes to performance improvements, I build exactly what's needed—plugins, integrations, or small changes without bloat.

Explore web development

Search this site

Start typing to search, or browse the knowledge base and blog.