WordPress Multisite Database Tutorial
In this tutorial I would like to dive deep into how the database works with WordPress Multisite installed, so if you’re still wondering, “Does wordpress multisite use one database?” then this tutorial is exactly for you.
However, having some basic WordPress database knowledge before reading this tutorial wouldn’t hurt.
As you probably know WordPress Multisite network isn’t being installed out of the box, usually a normal WordPress site gets upgraded into a Multisite. What does it mean? Of course, it means that we will have all the default database tables like wp_posts, wp_postmeta, wp_users even wp_options unchanged after the migration into a multisite.
But once you hit the “Install” button all the new tables are going to be created.

Multisite Database Tables Structure Explained
wp_blogs
This table contains information about each blog (sub-site) of a network.

| Column | Description |
|---|---|
blog_id | Unique integer identifier for each blog. |
site_id | Did you know that WordPress kind of supports multiple multisite networks on the same WordPress installation? Though I never knew any WordPress website which is that colossal. So, this column value is the ID of the network. It can be found in wp_site table. |
domain | Base domain. In the screenshot above domain is the same because I installed only one network and used subdirectories for blogs, not subdomains. |
path | Path to the blog homepage relative to the blog base domain. |
registered | The time when this blog has been created. In Y-m-d H:i:s format. |
last_updated | Shows the latest time when a post (of any custom type) was published or updated on the blog. |
lang_id | If you’ve just installed your blog and have not changed the language, this parameter value will be 0, but if you change the language even once a time, this value will become and remains 1. |
public, archived, mature, spam, deleted | If you go to “Sites > All sites” in your super admin dashboard and then click the “Edit” link on the non-main blog, you will see all these attributes there. Check the screenshot below. |

wp_blogmeta
When you update the WordPress version where the network is running, sometimes databases of some of the websites should be upgraded manually, and in that case, this table contains the information about the current database revision of the specific blogs.
Before WordPress 5.1 version it was wp_blog_versions table.
It was suggested to move some options from wp_#_options to wp_blogmeta, for example, admin_email and blogname, but it was never accomplished and at this moment, this table only contains db_version and db_last_updated information of every subsite. That’s also pretty much the reason, why my Duplicate Site for WordPress Multisite plugin doesn’t even copy the information in this table.
wp_registration_log

If you take a look at the screenshot above, you can see that we have the same user email but different blog_id and date_registered column values. So this table logs the time when a specific user has been added to a specific blog.
| Column | Description |
|---|---|
ID | The unique auto-increment number. Actually, it doesn’t mean anything. |
email | Email of the user who has created this blog. |
IP | The IP address of the user. |
blog_id | ID of a subsite where the user is registered. |
date_registered | Registration date and time in Y-m-d H:i:s format. |
wp_signups
This table is kind of specific – it stores user registration records. So, if you’re just about to add a user manually via the network dashboard and even if you then assign the user to a specific website – nothing will happen with this table, it will remain empty.
What you need to do is first of all make sure that user registration is allowed on your network:

Below you can see an example of a registered but not yet activated user:

domain, path, title and meta are empty for this user because the user hasn’t been assigned to any blogs yet.| Column name | Description |
|---|---|
signup_id | The unique auto-increment ID of the sign-up. |
domain | Base domain or subdomain of the blog the user was assigned to during the sign-up. |
path | Path of the blog homepage related to the domain. |
title | Title of the blog. |
user_login | Username. |
user_email | Email of the user. |
registered | Registration date and time in Y-m-d H:i format. |
activated | Date and time of the activation (when a user clicks a link in the confirmation email). |
active | 1 — activated, 0 — not activated. |
activation_key | Activation key which this user received by email. |
meta | Additional information as a serialized string. |
wp_site
On a regular WordPress Multisite install this table doesn’t usually have a lot of data:

The question comes to mind, why do we even need this table in the first place?
The thing is that WordPress is supposed to be extended not only to a multisite network but also to a network of multisite networks! And this table is a ground for that.
wp_sitemeta
In case you’re familiar with non-multisite database tables then I can say that the purpose of this table is similar to wp_options one. Though it looks like a meta table (wp_postmeta, wp_usermeta etc).
See it yourself:

This table, by the way, is also a part of the idea of a network of multisite networks. And by the way, functions get_site_option() and update_site_option() work directly with this table.
| Column | Description |
|---|---|
meta_id | The unique auto-increment ID of the row. |
site_id | ID of the Network. If you don’t use multiple networks within one WordPress installation, this parameter always remains 1. |
meta_key | Option name. |
meta_value | Option value. |
Multisite Indexer database structure
Some time ago, I developed a plugin that allows to query all the posts across the multisite network in a single query. In order to accomplish something like this without huge performance issues I needed to create additional tables in the database and to index network posts there.
So the plugin creates an additional set of tables:
wp_network_posts,wp_network_postmeta– indexed posts and post meta are stored here,wp_network_terms,wp_network_term_relationships,wp_network_term_taxonomy– indexed taxonomy terms and their relationships,wp_network_log– just a debug log,wp_network_rebuildqueue– information about the index rebuild process (if any is in progress).
What Happens with Standard WordPress Tables When Running a Multisite Network?
Just a couple of things:
wp_usersandwp_usermetatables become global for all network blogs. So, it doesn’t matter, how much subsites in your network you have, all the users (shared users) and their meta data will be stored in these tables.wp_userstable will be slightly modified, though – at the end of it, you can find two more columns – “spam” and “deleted”.- All the other blog-related tables are going to be duplicated for each blog with the number (blog ID) after the prefix. So, for the second installed blog, the prefix will be
wp_2_(unless you’re using a custom prefix of course).
Get Table Prefix in WordPress Multisite
Now you know that the prefixes of subsite-related tables and the global database prefix are going to be slightly different.
I guess you know how to get a blog prefix from $wpdb object?
global $wpdb;
$prefix = $wpdb->prefix; // wp_2_ , wp_3_, etcIf you would like to get a global database prefix, then you can use this:
global $wpdb;
$prefix = $wpdb->base_prefix; // wp_How to Extract a Single Site from WordPress Multisite Database?
Though we could consider this as a custom development work, which, by the way, my team is happy to help you with (just leave us a message), I would like to give you a step-by-step here.
- We need all the tables with a specific blog ID prefix (
wp_2_orwp_3_or so), export and import them into a new database. Change the prefix. - Export and import global tables
wp_usersandwp_usermeta. But if you want only specific blog users to be exported, you should do it manually I suppose. - Remove
spamanddeletedcolumns from the just importedwp_userstable.
Misha Rudrastyh
Hey guys and welcome to my website. For more than 10 years I've been doing my best to share with you some superb WordPress guides and tips for free.
Need some developer help? Contact me
Hi, I followed one tutorial and enabled multisite for some existing sites which lost due to hack but database tables are showing 198 tables with prefix nfmr_users and another wp_permitcarry_users
It looks like subdomain using different set of tables and domain using different set
How I make sure that example.com connecting to which tables
How I make sure that site1.example.com connecting to which tables
Please suggest!
Hey,
Just open your
wp-config.phpfile and find the line with the table prefix.Example:
It means that all tables with
wp_hello_andwp_hello_2_,wp_hello_3_,wp_hello_X_prefixes are connected to this multisite install.Hi, excellent post.
Is there a way to share options between all sites? I mean, in the main site store some settings, through an administration screen for example. After that, those settings would be available for each site.
Thanks!
Hi Carlos,
Thank you!
Yes, I think it is possible.
What if I want the table prefixes to be meaningful. E.g. instead of “wp_” and “wp_2” and “wp_3” etc. I want “main_”, “blog1_” and “store1” etc.
Hi John,
Oh, I am not sure it is any way possible, at least because I know some of the WordPress functions which rely on “_2” and “_3” part specifically.
But of course you can use it like “blog_”, “blog_2”, “blog_3” without problems, here is a tool which will help you to change the prefix.