Design Decisions

This page lists a number of important design decisions that come up frequently, and attempts to explain and cross-reference the reasoning behind them.

Absolute versus relative URLs Absolute versus relative URLs

WordPress stores absolute URLs in the database. Relative URLs are not used for a variety of reasons. Dynamically generated websites need permanent URLs (permalinks), so absolute URIs make more sense. WordPress has a variety of functions to call a site domain and various folders in plugins and themes so that relative URLs are not necessary. When moving domains, there are search and replace tools for switching domains in the database.

Why relative URLs are not good Why relative URLs are not good

Content is migratory. That is to say that the content, which is in the database, might not always be displayed within the context of “your site”. Content can be displayed in a variety of places. For example, an RSS feed of your content can be pulled into Google Reader and displayed there. Or users can use feed readers of their own. Or the content can be pulled from your site using microformats and displayed somewhere else. A user will never know where the content is going to be. Therefore an absolute URL is necessary within that content to ensure that it always points to a specific point, regardless of where it’s displayed.

Permalinks are malleable. The content of a post can be displayed on, on,, and so on. A relative URL would not be valid unless it is “root-relative”, meaning that it started with a / character, to refer to the root of the site. Even then, if a site is moved from one subdirectory to another, the root-relative URL would still need to change, and changing the content in the database to adjust would be necessary.

Moving is easier with absolute URLs. For example, assume a user is moving from to Doing a search and replace in the database for "" and replacing that is very easy and unlikely to be problematic. One might say that a root-relative URL would not need to change at all in such a case, and this is true, but what if the content needs to be moved from to The root-relative URLs still need to change in such a case, and now there isn’t a simple to find string, such as "" to search and replace on.

Also, within the content of posts themselves, absolute URLs are easier to manage.

It has been suggested that if WordPress were to be able to do all of this over, we may have instead opted for relative URLs. This is true, and making adjustments to our current approach – or reconsidering it in its entirety – does remain a distinct possibility in the future. See #17048.

Top ↑

No support for forwarding headers for HTTPS or IP addresses No support for forwarding headers for HTTPS or IP addresses

Many load balancers and proxy servers forward HTTP headers for HTTPS, IP addresses, and more. These typically take the form of HTTP_X_FORWARDED_FOR (X-Forwarded-For), for remote IP addresses, and HTTP_X_FORWARDED_PROTO (X-Forwarded-Proto), for whether traffic is going over the HTTPS protocol. Occasionally other information needs to be forwarded, like the server port.

If WordPress blindly listened to these headers – especially for protocols – there is a risk of infinite redirects and general breakage. To make matters worse, these are not formal standards, and are rather freeform. As a result, many web server and  configurations do this differently. For example, one configuration might prepend “HTTP_”, resulting in HTTP_HTTPS. What should be done instead is a server should either pass properly mapped headers to PHP, or some code can do the mapping in wp-config.php. For example:

if ( isset( $_SERVER['HTTP_X_FORWARDED_PROTO'] ) && 'https' === $_SERVER['HTTP_X_FORWARDED_PROTO'] ) )
    $_SERVER['HTTPS'] = 'on';

See also: #9235, #15009, #15733, #19337, #24394, etc.

Top ↑

Whitelisting oEmbed providers Whitelisting oEmbed providers

We have a certain standard for oEmbed providers in core. In order to add a new one to the existing whitelist, they must:

  • be well-established, popular, and mainstream services,
  • properly and fully implement the oEmbed specification,
  • and clearly be a trusted provider.

Security is important with oEmbed, because it is dealing with raw, unfiltered HTML, which is inherently dangerous due to arbitrary JavaScript and object embedding. It is therefore paramount that the provider can be trusted. But trust is more than about security — the service must also be “built to last.” If a provider ever stops supporting oEmbed, sites start to lose content they previously trusted would stay embedded permanently.  Or, if a dead startup’s domain expires or is acquired, it could be an easy vector for malware. Nascent services are just too fragile to be added for core.

With regards to establishment and popularity, there are a number of things that can be considered, such as:

  • Is the service is popular enough for core developers to have heard of it before? Is it “mainstream?”
  • If similar services are already supported, how does this service compare in terms of size, features, and backing?
  • Does this service have a large following on Twitter, Facebook, or other social media?  Is its Twitter account verified?
  • Is its oEmbed endpoint clearly established and properly documented? (Sometimes, they are just a developer’s pet project that may not be supported.)
  • Does the oEmbed endpoint work with WordPress’ oEmbed auto-discovery? If not, could it be made to work with additional HTML tags or attributes being whitelisted?
  • Does the service make an effort to build relationships with developers, such as through robust APIs?
  • How old is the service?
  • Does it have a well-established Wikipedia article? (Seriously.)
  • Has anyone written a WordPress plugin that leverages the service in some way, whether adding it as an oEmbed provider, creating a shortcode, or leveraging other APIs of the service? Do these plugins have any noticeable adoption or traction that would indicate usage and demand?
  • Is the provider frequently proposed?

Individually, these are all very anecdotal. But when considered holistically, it paints a pretty decent picture.

Top ↑

Unfiltered HTML for editors, administrators; multisite Unfiltered HTML for editors, administrators; multisite

Users with Administrator or Editor roles are allowed to publish unfiltered HTML in post titles, post content, and comments. WordPress is, after all, a publishing tool, and people need to be able to include whatever markup they need to communicate. Users with lesser privileges are not allowed to post unfiltered content.

If you are running security tests against WordPress, use a lesser privileged user so that all content is filtered. You may report security issues to For more, see Reporting Security Vulnerabilities.

If you are concerned about an Administrator putting XSS into content and stealing cookies, note that all cookies are marked for HTTP only delivery and are divided into privileged cookies used for admin pages and lesser-privileged cookies used for public-facing pages. Content is never displayed unfiltered in the admin. Regardless, an Administrator has wide-ranging super powers among which unfiltered HTML is a lesser one.

In WordPress multisite, only super administrators can publish unfiltered HTML, as all other users are considered untrusted.

To disable unfiltered HTML for all users, including administrators and super administrators, you can add define( 'DISALLOW_UNFILTERED_HTML', true ); to wp-config.php.

Top ↑

Only owner-writeable is supported on upgrade, not group writeable Only owner-writeable is supported on upgrade, not group writeable

See #10205.

Top ↑

Some esoteric MySQL settings are not supported Some esoteric MySQL settings are not supported

WordPress does not support MySQL strict mode or autocommit = 0. #8857, #16821, #16429.