wp-config.php is the master configuration file for every WordPress installation. It tells WordPress how to connect to the database, sets security keys, and turns on dozens of optional features through PHP constants. Edit it correctly and you unlock debug logging, memory bumps, auto-update controls, and security hardening. Edit it wrong and your site goes down hard.
This guide covers what’s actually in wp-config.php, the 20-ish constants worth knowing, how to edit the file safely, and the modern patterns (WP_ENVIRONMENT_TYPE, WP-CLI config commands) that most tutorials skip.
What wp-config.php does
Every time WordPress loads a page, the first thing it reads is wp-config.php. The file:
- Provides database credentials so WordPress can connect to MySQL/MariaDB
- Sets cryptographic keys and salts that secure cookies and sessions
- Defines the table prefix (so you can run multiple WordPress sites on one database)
- Toggles features through PHP constants (debug mode, memory limits, auto-updates, file editing)
- Loads
wp-settings.php, which boots the rest of WordPress
WordPress ships with wp-config-sample.php as a template. The installer copies and renames it during setup; if you install manually, you do the rename yourself.
Where to find wp-config.php
By default, wp-config.php sits in the WordPress root directory, alongside wp-admin/, wp-content/, and wp-includes/. On a typical Linux host the path looks like /home/username/public_html/wp-config.php.
Three common ways to access it:
- Open the File Manager in cPanel or hPanel, navigate to
public_html/, right-clickwp-config.php, and choose Edit. - Connect with an FTP or SFTP client (FileZilla, Cyberduck, Transmit), download
wp-config.php, edit locally, and upload it back. - Open an SSH session and edit in place with
nano /home/username/public_html/wp-config.php(orvim, your call).
WordPress also supports moving the file one directory above the WordPress root for security. If you don’t see wp-config.php in public_html/, check the parent directory.
Always make a backup before editing. Download a copy named wp-config.backup.php first. A single missing semicolon can take the entire site offline.
The structure of a wp-config.php file
A clean wp-config.php follows this layout, top to bottom:
<?php
/**
* 1. Database settings
*/
define( 'DB_NAME', 'database_name' );
define( 'DB_USER', 'database_user' );
define( 'DB_PASSWORD', 'database_password' );
define( 'DB_HOST', 'localhost' );
define( 'DB_CHARSET', 'utf8mb4' );
define( 'DB_COLLATE', '' );
/**
* 2. Authentication unique 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' );
/**
* 3. Table prefix
*/
$table_prefix = 'wp_';
/**
* 4. Custom constants (debug, security, performance, etc.)
* All of your custom edits go here.
*/
define( 'WP_DEBUG', false );
/* That's all, stop editing! Happy publishing. */
if ( ! defined( 'ABSPATH' ) ) {
define( 'ABSPATH', __DIR__ . '/' );
}
require_once ABSPATH . 'wp-settings.php';
Custom constants belong between the table prefix and the /* That's all, stop editing! */ comment. Anything below that comment may not load correctly.
Database configuration
The first six constants tell WordPress how to connect to your database:
DB_NAME→ the database name (something likewp_mysite)DB_USER→ the database username with read/write permissionsDB_PASSWORD→ that user’s passwordDB_HOST→ usuallylocalhost, sometimes a remote host likemysql.example.com:3306DB_CHARSET→ almost alwaysutf8mb4on modern installsDB_COLLATE→ leave empty unless your host requires otherwise
If you ever migrate hosts or rename the database, these are the four values you update. Get them wrong and you’ll see “Error establishing a database connection.”
Authentication keys and salts
The eight cryptographic strings sign and encrypt cookies, nonces, and password hashes. Generate fresh values from api.wordpress.org/secret-key/1.1/salt/ and paste them into your file.
Rotating these keys is a good security move. After rotation, every existing user gets logged out (their old session cookies become invalid). Use it as a forced logout if you suspect a credential leak. WP-CLI handles this in one command:
wp config shuffle-salts
The constants worth knowing
WordPress recognizes dozens of optional constants. These are the ones that come up in real projects, grouped by purpose.
Debug
// Turn on debugging
define( 'WP_DEBUG', true );
// Write errors to wp-content/debug.log instead of displaying them
define( 'WP_DEBUG_LOG', true );
// Hide errors from front-end visitors (recommended on production)
define( 'WP_DEBUG_DISPLAY', false );
@ini_set( 'display_errors', 0 );
// Log every database query (for performance debugging)
define( 'SAVEQUERIES', true );
// Use unminified core scripts and styles for development
define( 'SCRIPT_DEBUG', true );
The four-line debug block (DEBUG + LOG + DISPLAY off + ini_set) is the safest production debugging setup. Errors go to a log file you can read at your leisure, and visitors never see a PHP warning.
URLs
define( 'WP_HOME', 'https://example.com' );
define( 'WP_SITEURL', 'https://example.com' );
These two constants override the URL settings in Settings → General. Useful when you’ve cloned or migrated a site and the database still has the old URL, or when you’ve locked yourself out by entering a bad URL in the admin. Setting them in wp-config.php is faster than editing the database directly.
Memory and performance
// PHP memory limit for the front-end
define( 'WP_MEMORY_LIMIT', '256M' );
// Higher memory limit for admin pages (imports, plugin updates, etc.)
define( 'WP_MAX_MEMORY_LIMIT', '512M' );
// Enable persistent caching (object/page cache plugins look for this)
define( 'WP_CACHE', true );
For a deeper walkthrough on memory limits including the .htaccess and php.ini routes, see how to increase the WordPress memory limit.
Security hardening
// Block the theme/plugin file editor in wp-admin
define( 'DISALLOW_FILE_EDIT', true );
// Block all file modifications from wp-admin (no plugin/theme installs or updates)
define( 'DISALLOW_FILE_MODS', true );
// Force HTTPS for the admin and login screens
define( 'FORCE_SSL_ADMIN', true );
// Block all outgoing HTTP requests except to whitelisted hosts
define( 'WP_HTTP_BLOCK_EXTERNAL', true );
define( 'WP_ACCESSIBLE_HOSTS', 'api.wordpress.org,*.github.com' );
DISALLOW_FILE_EDIT is a quick win on every site you build. There’s no good reason to edit theme files from the wp-admin UI in 2026, and an attacker who steals an admin login can use the editor to inject malicious PHP. Turn it off.
Auto-updates
// Disable all automatic updates (core, plugins, themes, translations)
define( 'AUTOMATIC_UPDATER_DISABLED', true );
// Allow only minor core updates (5.9.1 -> 5.9.2). Default behavior.
define( 'WP_AUTO_UPDATE_CORE', 'minor' );
// Allow all core updates including major releases
define( 'WP_AUTO_UPDATE_CORE', true );
// Disable all core updates
define( 'WP_AUTO_UPDATE_CORE', false );
Most sites should stay on the default (minor updates only) so security patches apply automatically. Major-version auto-updates are riskier because they sometimes break plugin compatibility.
Cron
// Stop WordPress from triggering wp-cron on every page load
define( 'DISABLE_WP_CRON', true );
WordPress’s built-in cron runs scheduled tasks on every front-end page load. On busy sites that adds overhead. Disable it here, then set up a real system cron job that pings wp-cron.php every five minutes:
*/5 * * * * curl https://example.com/wp-cron.php?doing_wp_cron > /dev/null 2>&1
Content settings
// Limit post revisions to 10 per post (default is unlimited)
define( 'WP_POST_REVISIONS', 10 );
// Disable revisions entirely
define( 'WP_POST_REVISIONS', false );
// Slow the autosave interval from the default 60 seconds
define( 'AUTOSAVE_INTERVAL', 300 );
// Days before trashed posts are permanently deleted (default 30)
define( 'EMPTY_TRASH_DAYS', 7 );
WP_POST_REVISIONS is one of the easiest database-bloat fixes. A 5-year-old site with 500 posts and unlimited revisions can have 50,000+ revision rows. Capping at 10 per post is a sensible default.
Environment type (modern pattern)
// Tell WordPress which environment this is
define( 'WP_ENVIRONMENT_TYPE', 'production' ); // or 'staging', 'development', 'local'
WordPress 5.5+ supports environment types. Plugins and themes can check wp_get_environment_type() to behave differently between local, staging, and production. Caching plugins use it to skip cache priming on dev environments. Stripe and PayPal plugins use it to switch to test keys. Setting this constant correctly avoids a lot of “I broke production” moments.
A copy-paste debug block
When something breaks, this is the block to drop in (above the “stop editing” comment) so you can see what’s going wrong without exposing errors to visitors:
// Debug block (remove or set to false in production)
define( 'WP_DEBUG', true );
define( 'WP_DEBUG_LOG', true );
define( 'WP_DEBUG_DISPLAY', false );
@ini_set( 'display_errors', 0 );
define( 'SCRIPT_DEBUG', true );
define( 'SAVEQUERIES', true );
After enabling, reproduce the issue, then read wp-content/debug.log for stack traces. Turn the block off again once you’re done; running with WP_DEBUG on permanently slows the site and clutters the log.
Editing wp-config.php with WP-CLI
If your host gives you SSH access, WP-CLI handles every common edit without opening the file:
# See every constant currently defined
wp config list
# Get a single value
wp config get DB_NAME
# Set or add a constant
wp config set WP_DEBUG true --raw
wp config set WP_MEMORY_LIMIT 256M
# Delete a constant
wp config delete WP_DEBUG
# Generate fresh keys/salts (forces all users to log out)
wp config shuffle-salts
# Validate the file syntactically
wp config has DB_NAME && echo OK
WP-CLI writes constants in the right place automatically (between the table prefix and the “stop editing” comment) and won’t corrupt your file with a typo. For automated deployments and config management, this is the path.
Security best practices
Move wp-config.php up one directory if you can. WordPress checks the parent of its install root automatically, so a file at /home/user/wp-config.php still works for a WordPress install at /home/user/public_html/. Once it’s outside the web root, no HTTP request can reach it.
Tighten file permissions to 600 (or 640 if your host requires group read). Only the owner needs read/write access. From SSH, that’s chmod 600 wp-config.php; via cPanel, change permissions in File Manager.
Add a defense-in-depth block in your root .htaccess so direct HTTP requests get rejected before PHP even runs:
<Files wp-config.php>
Require all denied
</Files>
Never commit wp-config.php to Git. If you version-control your site code, list it in .gitignore and keep the credentials in environment variables, a secrets manager, or a separate untracked include file. Repos leak; production credentials in a leaked repo are an instant compromise.
Rotate keys and salts periodically (at least once a year, immediately after any suspected credential leak). One command does it: wp config shuffle-salts. Every existing user gets logged out, which is exactly what you want after a security event.
Common mistakes to avoid
A few patterns reliably break sites. Editing without a backup is the most common; a single missing semicolon takes the site offline, and recovery is much faster from a saved copy than from memory. Download the original file before any edit, every time.
Adding constants below the /* That's all, stop editing! */ comment is the second most common mistake. WordPress already loaded wp-settings.php by that point, and your constants get ignored. Custom constants belong above that line.
Saving with a UTF-8 byte-order mark (BOM) is a less obvious failure mode. Some editors silently add the BOM, which breaks WordPress in subtle ways (headers already sent, blank pages on activation). Make sure your editor is set to “UTF-8 without BOM” or “UTF-8” specifically (not “UTF-8 with BOM”).
Hardcoding production credentials in committed code is the security version of the same mistake. If a public repo is ever pushed, the database is one git clone away from compromise. Use environment variables, a secrets manager, or a separate untracked include file for anything sensitive.
Leaving WP_DEBUG on in production slows the site and exposes file paths in error messages, which is useful information for an attacker. Enable it only when you’re actively debugging, then turn it off.
Frequently asked questions
What is the wp-config.php file used for?
It stores the database credentials WordPress uses to connect to MySQL, sets the cryptographic keys that secure cookies and sessions, and defines the optional PHP constants that toggle features like debug mode, memory limits, auto-updates, and security hardening. Every WordPress page load reads wp-config.php first.
Where is wp-config.php located?
By default it sits in the WordPress root directory, alongside the wp-admin/, wp-content/, and wp-includes/ folders. On most hosts that’s public_html/wp-config.php or ~/public_html/wp-config.php. WordPress also supports moving the file one directory above the root (e.g., /home/user/wp-config.php when the WordPress root is /home/user/public_html/). If you don’t see it in the root, check the parent directory.
How do I create wp-config.php manually?
Copy wp-config-sample.php (which ships with every WordPress install) and rename the copy to wp-config.php. Open it in a text editor, fill in the four database constants (DB_NAME, DB_USER, DB_PASSWORD, DB_HOST), then paste fresh authentication keys from api.wordpress.org/secret-key/1.1/salt/ over the placeholder values. Save and upload to the WordPress root.
Is it safe to edit wp-config.php?
Yes, with two precautions. First, always download a backup copy before making changes. Second, edit it through your host’s file manager, FTP, SSH, or WP-CLI; never use the WordPress admin (no UI exists for that, and you don’t want one). A single missing semicolon takes the site offline, but the backup makes recovery a 30-second copy-back.
Why am I seeing ‘Error establishing a database connection’?
One of your four database constants is wrong: DB_NAME, DB_USER, DB_PASSWORD, or DB_HOST. Double-check the values against your host’s database admin panel. Other causes: the database server is down (rare on managed hosts), the database user doesn’t have permission for that database, or the host name needs a port (mysql.example.com:3306).
How do I increase the WordPress memory limit through wp-config.php?
Add define( 'WP_MEMORY_LIMIT', '256M' ); above the “stop editing” comment. For admin-only operations like plugin updates and large imports, also set define( 'WP_MAX_MEMORY_LIMIT', '512M' );. If neither change takes effect, your host has the PHP memory limit capped lower at the server level; the full memory-limit guide covers the .htaccess and php.ini fallbacks.
Wrap-up
wp-config.php is small but powerful. Most sites only ever touch the database section and a handful of constants (debug, memory limit, post revisions). Keep a backup, edit between the table prefix and the “stop editing” comment, and lean on WP-CLI when your host gives you SSH. For anything you’d commit to a code repository, use environment variables or a separate untracked config file so credentials never ship with your code.


