How WordPress Actually Boots: A Step-by-Step Walk Through wp-load.php
Table of Contents
Most developers use WordPress daily, but very few understand what actually happens when a request hits a site.
This guide breaks down the complete boot process — starting from wp-load.php — with practical debugging examples and performance insights.
Visual Overview of the Boot Process
This diagram shows the full execution flow:
index.php ↓ wp-blog-header.php ↓ wp-load.php ↓ wp-config.php ↓ wp-settings.php ↓ Plugins → Theme → Hooks ↓ WP_Query → Template Loader
Step 1: wp-load.php (Bootstrap Entry)
This file initializes WordPress by locating and loading wp-config.php.
<?php
if ( file_exists( ABSPATH . 'wp-config.php' ) ) {
require_once ABSPATH . 'wp-config.php';
}Key Role:
- Locates configuration file
- Starts bootstrap process
- Supports custom directory structures
Debug Example
<?php
error_log( 'wp-load.php executed' );Step 2: wp-config.php (Configuration Layer)
This file defines environment settings and database credentials.
<?php
define( 'DB_NAME', 'my_database' );
define( 'WP_DEBUG', true );Advanced Conditional Debugging
<?php
if ( $_SERVER['REMOTE_ADDR'] === 'YOUR_IP' ) {
define( 'WP_DEBUG', true );
}Step 3: wp-settings.php (Core Boot Engine)
This is where WordPress loads its full environment.
3.1 Load Core Files
<?php
require ABSPATH . WPINC . '/load.php';
require ABSPATH . WPINC . '/plugin.php';3.2 Initialize Plugin System
<?php
\do_action( 'muplugins_loaded' );
\do_action( 'plugins_loaded' );How WordPress loads “must-use” plugins
WordPress starts by loading all the “must-use” plugins. The use of the term plugin is deceiving here. WordPress doesn’t care if they’re plugins or not.
WordPress scans for PHP files in the root of the directory defined by “WPMU_PLUGIN_DIR” (default is “mu-plugins”). It won’t scan for folders like it does in the “plugins” folder. Once it’s done scanning, WordPress includes each file in alphabetical order. Changing the file name is the only way to change that order.
MU Plugin Example
<?php
// wp-content/mu-plugins/debug.php
\add_action( 'muplugins_loaded', function() {
error_log( 'MU plugins loaded first!' );
});3.3 Load Active Plugins
<?php
$active_plugins = \get_option( 'active_plugins' );
foreach ( $active_plugins as $plugin ) {
include_once WP_PLUGIN_DIR . '/' . $plugin;
}How WordPress loads active plugins
<?php
/**
* Ensures that the plugin is always the first one to be loaded.
*
* @param array $active_plugins
*
* @return array
*/
public function ensure_loaded_first( array $active_plugins )
{
$basename = plugin_basename( __FILE__ );
$key = array_search($basename, $active_plugins);
if (false !== $key) {
array_splice( $active_plugins, $key, 1);
array_unshift( $active_plugins, $basename );
}
return $active_plugins;
}
\add_filter( 'pre_update_option_active_plugins', 'ensure_loaded_first' );
\add_filter( 'pre_update_site_option_active_sitewide_plugins', 'ensure_loaded_first' );First, you need the value that WordPress stores in “active_plugins” for your plugin. You get that value by using the “plugin_basename” function. You use “array_search” to find the array key that stores that value. If the array key isn’t false, it means that your plugin is active. You remove the value from the array using “array_splice” and the array key. You can then reinsert it at the top with “array_unshift“.
pluggable.php
Once WordPress finished loading all the “must-use” and active plugins, it loads “pluggable.php”. It contains all WordPress pluggable functions. These are functions that plugins can override.
functions.php
To clarify, we’re talking about the “functions.php” found in the current theme here. Unless the theme is a child theme. In that case, we’re talking about the parent theme’s and the child theme’s “functions.php”. That’s because the two have a special relationship.
WordPress loads the child theme’s “functions.php” before the parent theme’s. This is something to keep in mind when you code a child theme. You won’t be able to use functions from the parent theme in the child theme right away. You have to wait until WordPress finishes the theme setup.
It’s worth noting that WordPress loads “functions.php” after “pluggable.php”. A theme can’t use it to override core WordPress functions. This is how WordPress limits that ability to plugins only.
Performance Debugging
<?php
\add_action( 'plugins_loaded', function() {
error_log( 'Plugins loaded at: ' . microtime( true ) );
});3.4 Theme Initialization
<?php
\do_action( 'setup_theme' );<?php
\add_action( 'after_setup_theme', function() {
error_log( 'Theme initialized' );
});3.5 Global Objects
WordPress initializes key globals:
$wpdb$wp_query$wp_rewrite
<?php
global $wpdb;
$results = $wpdb->get_results( "SELECT ID FROM $wpdb->posts LIMIT 5" );3.6 The init Hook
<?php
\do_action( 'init' );Custom Post Type Example
<?php
\add_action( 'init', function() {
\register_post_type( 'book', array(
'public' => true,
'label' => 'Books'
));
});Step 4: Request Parsing
<?php
$wp->parse_request();
$wp->query_posts();At this stage, WordPress determines what content should be displayed.
Step 5: Template Loading
<?php
include( \get_query_template( 'index' ) );This loads the appropriate theme template like:
- single.php
- page.php
- archive.php
Full Boot Trace Example
<?php
\add_action( 'muplugins_loaded', fn() => error_log( '1. muplugins_loaded' ) );
\add_action( 'plugins_loaded', fn() => error_log( '2. plugins_loaded') );
\add_action( 'setup_theme', fn() => error_log( '3. setup_theme' ) );
\add_action( 'after_setup_theme', fn() => error_log( '4. after_setup_theme' ) );
\add_action( 'init', fn() => error_log( '5. init' ));
\add_action( 'wp_loaded', fn() => error_log( '6. wp_loaded' ));Different boot approaches
WordPress needs to load differently in some situations, and based on that, it needs to change the way it loads.
Multisite
WordPress integrates multisite functionality directly into its normal loading process. It checks the is_multisite() function at key points, and when it returns true, additional multisite-specific files are loaded.
These files are easy to recognize because they use the ms- prefix instead of the usual wp- (or no prefix). For example, ms-settings.php handles most of the multisite bootstrapping, similar to how wp-settings.php works for a standard installation. There are a couple of exceptions to this naming pattern.
One is ms-blogs.php, which provides functions for working with multisite database tables.
Another is sunrise.php. This file is conditionally loaded by ms-settings.php when the SUNRISE constant is defined. It allows developers to override the default site and blog resolution process by setting the current_site and current_blog variables before WordPress does. A well-known use case is domain mapping. While official documentation is limited, more details can be found in the original Trac discussion.
WordPress Admin
All admin pages in WordPress start their execution through wp-admin/admin.php. This file begins by defining the WP_ADMIN constant, which acts as a flag indicating that the current request is for the admin area.
It then loads wp-load.php, triggering the standard WordPress initialization process. Once that completes, WordPress continues with additional admin-specific setup.
The full admin loading sequence is quite extensive and goes beyond the scope covered here, so it’s best explored separately.
AJAX
AJAX requests in WordPress are handled through a single entry point: admin-ajax.php.
This file is used for all AJAX calls—whether the user is logged in or not, and whether the request originates from the admin area or the frontend. Because of this, it needs to accommodate a wide range of scenarios.
The process begins by defining the WP_ADMIN constant (to support admin-related logic) and a dedicated DOING_AJAX constant, which signals that the current request is an AJAX operation.
Unlike standard admin requests, it does not follow the full admin loading flow. Instead, it loads WordPress via wp-load.php, similar to frontend requests. After that, it explicitly includes admin APIs through wp-admin/includes/admin.php.
Finally, WordPress registers AJAX-specific hooks, all of which are defined in ajax-actions.php. This file is only loaded during AJAX requests.
⚡ Performance Insights
- Most performance issues happen during bootstrap
- Heavy plugins slow down early execution
- Too many autoloaded options increase memory usage
- Hooks like
initare common bottlenecks
Key Takeaways
wp-load.phpstarts the processwp-config.phpdefines environmentwp-settings.phploads core system- Hooks control execution flow
- Plugins and themes run during bootstrap
Final Thoughts
Understanding how WordPress boots gives you a major advantage in debugging, optimization, and plugin development.
Instead of guessing, you can now pinpoint exactly where and when your code executes.
FAQ
What does wp-load.php do in WordPress?
wp-load.php is the bootstrap entry point of WordPress. It locates and loads wp-config.php, which then initializes the entire WordPress environment.
How does WordPress boot or initialize?
WordPress boots by loading index.php, which includes wp-blog-header.php, then wp-load.php. From there, wp-config.php and wp-settings.php load core files, plugins, themes, and hooks before processing the request and rendering a template.
What is wp-settings.php responsible for?
wp-settings.php is the core boot engine of WordPress. It loads core files, initializes plugins, sets up the theme, defines global objects, and triggers key hooks like init.
In what order does WordPress load plugins?
WordPress first loads must-use (mu-plugins) from the mu-plugins directory in alphabetical order. After that, it loads active plugins defined in the database, followed by pluggable functions and theme files.
What are the most important WordPress hooks during boot?
Key WordPress boot hooks include muplugins_loaded, plugins_loaded, setup_theme, after_setup_theme, init, and wp_loaded. These control when plugins and themes execute during the loading process.
How does WordPress handle AJAX requests?
WordPress handles AJAX requests through admin-ajax.php. It defines DOING_AJAX and WP_ADMIN, loads the WordPress environment via wp-load.php, includes admin APIs, and executes registered AJAX hooks.
What is the difference between wp-load.php and wp-config.php?
wp-load.php is responsible for locating and loading wp-config.php, while wp-config.php defines the site's configuration, including database credentials and environment settings.
Why is understanding the WordPress boot process important?
Understanding the WordPress boot process helps developers debug issues, optimize performance, and correctly hook into the execution flow when building plugins or themes.