Essential wp-config.php Tweaks Every WordPress Site Should Have
The wp-config.php constants every agency should know - security hardening, performance settings, debug tools, and database configuration explained.
wp-config.php controls security, performance, database and debugging behaviour before WordPress fully loads. The highest-value entries are disabling the file editor, limiting post revisions, setting a real memory limit, and keeping debug output out of production.
wp-config.php is the most important file in any WordPress installation. It controls database connections, security keys, debug settings, memory limits, and dozens of behaviours that cannot be changed through the admin interface. Most developers set it up once and never look at it again - leaving performance and security improvements on the table.
This guide covers every wp-config.php constant worth knowing, grouped by category, with explanations of when and why to use each one.
Security hardening
Authentication keys and salts
Your WordPress install came with a set of authentication keys and salts. These are used to encrypt cookies and password hashes. If you migrated a site from somewhere else, regenerate them immediately:
Visit https://api.wordpress.org/secret-key/1.1/salt/ to generate a fresh set. Replace the existing block in wp-config.php:
define( 'AUTH_KEY', 'unique value here' ); define( 'SECURE_AUTH_KEY', 'unique value here' ); define( 'LOGGED_IN_KEY', 'unique value here' ); define( 'NONCE_KEY', 'unique value here' ); define( 'AUTH_SALT', 'unique value here' ); define( 'SECURE_AUTH_SALT', 'unique value here' ); define( 'LOGGED_IN_SALT', 'unique value here' ); define( 'NONCE_SALT', 'unique value here' );
Regenerating these logs out all existing sessions. Tell clients before doing it on a live site.
Disable file editing from the admin
The built-in theme and plugin editor is a direct PHP code execution interface for anyone who gets admin access. Disable it:
define( 'DISALLOW_FILE_EDIT', true );
Disable plugin/theme installation from the admin
For maximum-hardened client sites where you control deployments:
define( 'DISALLOW_FILE_MODS', true );
This prevents all file modifications from the admin, including updates. Only use this if you have a CI/CD process for updates, or if the site is completely static and never needs changes.
Force HTTPS for admin and login
define( 'FORCE_SSL_ADMIN', true );
Limit login attempts
wp-config.php cannot block brute force directly, but combined with a server-level fail2ban rule, you can lock out IPs after repeated failures. Add custom login error messages:
// Not a wp-config.php constant, but related: place in functions.php add_filter( 'login_errors', fn() => 'Incorrect credentials.' );
Set cookie domain explicitly
If you are running a multisite or have cookies behaving unexpectedly after SSL migration:
define( 'COOKIE_DOMAIN', 'yourdomain.com' );
Performance settings
WordPress memory limit
define( 'WP_MEMORY_LIMIT', '256M' ); // frontend define( 'WP_MAX_MEMORY_LIMIT', '512M' ); // admin operations
Limit post revisions
define( 'WP_POST_REVISIONS', 5 ); // keep 5 revisions, delete the rest // Or disable entirely: define( 'WP_POST_REVISIONS', false );
On a site with 5,000 posts and unlimited revisions, the wp_posts table can grow to hundreds of thousands of rows. Most are never used. 5 revisions is enough for a safety net.
Autosave interval
WordPress autosaves the editor every 60 seconds. This generates database writes and revision records. For busy editorial teams who frequently have the editor open:
define( 'AUTOSAVE_INTERVAL', 300 ); // every 5 minutes instead of 1
Empty trash automatically
By default WordPress keeps trashed posts for 30 days. For sites with high content turnover:
define( 'EMPTY_TRASH_DAYS', 7 ); // auto-delete after 7 days // Or disable trash entirely: define( 'EMPTY_TRASH_DAYS', 0 ); // immediately deleted, no undo
Disable WP Cron and use server cron
define( 'DISABLE_WP_CRON', true );
Add a proper server cron job:
*/5 * * * * cd /var/www/html && wp cron event run --due-now --quiet
This is important for sites with accurate scheduled publishing, email queues, or backup plugins that run on a schedule.
Enable object cache persistence
If you are using a Redis or Memcached object cache (via a drop-in or plugin), WordPress needs to know the cache should persist between requests. This is usually handled by the cache plugin, but occasionally needs a manual constant:
define( 'WP_CACHE', true );
Database configuration
Table prefix
Set during install, but worth documenting: the default wp_ prefix makes SQL injection attacks slightly easier because attackers know your table names. Change it during migration:
$table_prefix = 'site42_'; // custom prefix
Changing this on an existing install requires updating all table names and the prefix values in wp_options and wp_usermeta - use a plugin like Brozzme DB Prefix Change.
Database charset and collation
WordPress defaults to utf8mb4 which supports full Unicode including emoji. Only change this if you have a specific legacy reason:
define( 'DB_CHARSET', 'utf8mb4' ); define( 'DB_COLLATE', 'utf8mb4_unicode_ci' );
Database host with custom port
If your database server runs on a non-standard port:
define( 'DB_HOST', 'localhost:3307' );
Or with a Unix socket (faster than TCP on the same server):
define( 'DB_HOST', 'localhost:/var/run/mysqld/mysqld.sock' );
Debugging and development
Full debug mode
Never leave this on in production. Use it locally or on staging:
define( 'WP_DEBUG', true ); // enable error display define( 'WP_DEBUG_LOG', true ); // write errors to /wp-content/debug.log define( 'WP_DEBUG_DISPLAY', false ); // do not show errors publicly
Script debug mode
Forces WordPress to load unminified versions of scripts and styles. Useful when debugging a JS conflict in the admin:
define( 'SCRIPT_DEBUG', true );
Concatenate scripts (admin only)
WordPress concatenates admin scripts into a single request by default. If you are diagnosing a JavaScript conflict in the admin:
define( 'CONCATENATE_SCRIPTS', false );
Logging slow cron jobs
If you suspect a cron job is causing problems:
define( 'SAVEQUERIES', true ); // logs all DB queries - very verbose, remove after use
Multisite configuration
Enable multisite
define( 'WP_ALLOW_MULTISITE', true );
After enabling and running through the Network Setup screen, WordPress adds additional constants automatically:
define( 'MULTISITE', true ); define( 'SUBDOMAIN_INSTALL', false ); // false = subdirectory, true = subdomain define( 'DOMAIN_CURRENT_SITE', 'yourdomain.com' ); define( 'PATH_CURRENT_SITE', '/' ); define( 'SITE_ID_CURRENT_SITE', 1 ); define( 'BLOG_ID_CURRENT_SITE', 1 );
File system and uploads
Upload path
Change the default uploads directory:
define( 'UPLOADS', 'media' ); // instead of /wp-content/uploads/
FTP credentials for updates (rare)
If WordPress cannot write directly to the filesystem (unusual on modern setups), it falls back to FTP for updates:
define( 'FTP_HOST', 'ftp.yourdomain.com' ); define( 'FTP_USER', 'username' ); define( 'FTP_PASS', 'password' ); define( 'FS_METHOD', 'direct' ); // or 'ftpext', 'ftpsockets', 'ssh2'
Setting FS_METHOD to direct tells WordPress to write files directly without FTP, which is correct for most VPS and managed hosting setups where the web server user owns the files.
HTTPS and proxy settings
Site URL and home URL
Override the database values entirely:
define( 'WP_HOME', 'https://yourdomain.com' ); define( 'WP_SITEURL', 'https://yourdomain.com' );
Useful when migrating, or when the database has the wrong URL locked in after a failed migration.
Reverse proxy HTTPS detection
if ( isset( $_SERVER['HTTP_X_FORWARDED_PROTO'] )
&& 'https' === $_SERVER['HTTP_X_FORWARDED_PROTO'] ) {
$_SERVER['HTTPS'] = 'on';
}
Cookie path and site cookie path
For installs in subdirectories:
define( 'COOKIEPATH', '/' ); define( 'SITECOOKIEPATH', '/' );
A clean wp-config.php template
Here is a minimal, well-structured wp-config.php template that includes all the above:
<?php
// === Database ===
define( 'DB_NAME', getenv( 'DB_NAME' ) ?: 'database_name' );
define( 'DB_USER', getenv( 'DB_USER' ) ?: 'database_user' );
define( 'DB_PASSWORD', getenv( 'DB_PASSWORD' ) ?: 'database_password' );
define( 'DB_HOST', getenv( 'DB_HOST' ) ?: 'localhost' );
define( 'DB_CHARSET', 'utf8mb4' );
define( 'DB_COLLATE', 'utf8mb4_unicode_ci' );
// === Keys & Salts ===
// Generate from: https://api.wordpress.org/secret-key/1.1/salt/
define( 'AUTH_KEY', '...' );
define( 'SECURE_AUTH_KEY', '...' );
define( 'LOGGED_IN_KEY', '...' );
define( 'NONCE_KEY', '...' );
define( 'AUTH_SALT', '...' );
define( 'SECURE_AUTH_SALT', '...' );
define( 'LOGGED_IN_SALT', '...' );
define( 'NONCE_SALT', '...' );
// === Performance ===
define( 'WP_MEMORY_LIMIT', '256M' );
define( 'WP_MAX_MEMORY_LIMIT', '512M' );
define( 'WP_POST_REVISIONS', 5 );
define( 'AUTOSAVE_INTERVAL', 300 );
define( 'EMPTY_TRASH_DAYS', 7 );
define( 'DISABLE_WP_CRON', true );
define( 'WP_CACHE', true );
// === Security ===
define( 'DISALLOW_FILE_EDIT', true );
define( 'FORCE_SSL_ADMIN', true );
// === Debug (production: all false) ===
define( 'WP_DEBUG', false );
define( 'WP_DEBUG_LOG', false );
define( 'WP_DEBUG_DISPLAY', false );
define( 'SCRIPT_DEBUG', false );
// === URLs ===
define( 'WP_HOME', 'https://yourdomain.com' );
define( 'WP_SITEURL', 'https://yourdomain.com' );
// === Reverse proxy HTTPS ===
if ( isset( $_SERVER['HTTP_X_FORWARDED_PROTO'] )
&& 'https' === $_SERVER['HTTP_X_FORWARDED_PROTO'] ) {
$_SERVER['HTTPS'] = 'on';
}
// === Table prefix ===
$table_prefix = 'wp_';
/* Stop editing. */
if ( ! defined( 'ABSPATH' ) ) {
define( 'ABSPATH', __DIR__ . '/' );
}
require_once ABSPATH . 'wp-settings.php';
Using environment variables for credentials
Hardcoding database credentials in wp-config.php works, but committing that file to git is a common security mistake. Use environment variables instead:
define( 'DB_NAME', getenv( 'DB_NAME' ) ); define( 'DB_USER', getenv( 'DB_USER' ) ); define( 'DB_PASSWORD', getenv( 'DB_PASSWORD' ) );
Set the environment variables in your server config (Apache SetEnv, Nginx fastcgi_param, or a .env file loaded by a package like vlucas/phpdotenv). This way wp-config.php can safely be committed to version control without exposing credentials.
Managed hosts like Kinsta and Cloudways already inject database credentials as environment variables and provide a wp-config.php that reads from them.
Related reading
Frequently Asked Questions
What are the most important wp-config.php settings?
Should I disable the WordPress file editor?
How do I limit WordPress post revisions?
Is it safe to enable WP_DEBUG on a live site?
Where should new constants go in wp-config.php?
// new_articles
Get notified when new guides drop
Practical WordPress guides from a working agency owner. No filler. Unsubscribe any time.
Was this article helpful?
Thanks for the feedback!