← Back to blog

Where WordPress Playground stops working

The SandyWP team 6 min read

WordPress Playground runs a real WordPress in your browser tab, with no server anywhere. That is a genuinely impressive piece of engineering, and it is the right tool for a surprising number of jobs.

It also has hard limits, and most of them come from the same place: there is no server. This post covers where those limits actually bite, sourced to Playground's own documentation and issue tracker, and what to do when you hit one.

We build SandyWP, which gives you a throwaway WordPress on a real server. So read the comparison at the end with that in mind. The technical facts below are all from Playground's own sources, linked as we go.

What Playground actually is

Playground compiles PHP to WebAssembly and runs it inside the browser. WordPress core runs unmodified on top of that, with SQLite standing in for MySQL.

Nothing is installed and nothing is hosted. The Playground handbook puts the consequence plainly: it is "not a permanent server with an internet address", which limits connections to third-party services for automation, sharing, analysis, email, and backups.

That single sentence explains almost every limitation below.

Does WordPress Playground save my work?

Not reliably, and not by default.

Playground can persist a site to browser storage, but the official limitations page is blunt about what that means: "Autosaves are recovery points, not long-term backups." Browser storage can be cleared by storage pressure, private browsing, a profile change, or clearing site data.

The supported way to keep work is to export a ZIP. That is a manual step, and if you forget it before closing the tab, the site is gone.

This is fine for a five-minute experiment. It is not fine for a client demo you want to reopen next week, or for a bug reproduction a colleague needs to look at tomorrow.

Can Playground make HTTP requests to an API?

Partly, with conditions that break a lot of real plugins.

Browsers do not let WebAssembly open network sockets. Playground works around this by translating PHP HTTP calls into JavaScript fetch() requests, which is documented in the long-running network access issue. Two constraints follow from that:

  • Only https:// URLs work.
  • The remote server has to return permissive CORS headers, because the request is a browser fetch and is subject to the same-origin policy.

Most third-party APIs do not send CORS headers allowing arbitrary origins, because they were never designed to be called from a browser. Playground ships a CORS proxy to help, but the same issue notes the proxy is limited around supported headers, content types, and transfer sizes, and it is not applied to everything.

Direct libcurl and raw socket access are not supported. So a licence check, a payment gateway callback, an external analytics ping, or a plugin that talks to an SMTP server can all fail here for reasons that have nothing to do with the plugin being broken.

That is the trap: a plugin failing in Playground does not prove the plugin is faulty. If you are debugging, you need to rule out the environment first.

Does email work?

No, not in the way you need for testing.

Sending mail means opening a connection to a mail server, which is the socket problem again. The handbook lists email among the services affected by having no internet address.

So a contact form submission in Playground tells you the form rendered. It does not tell you whether the notification would arrive, what the message body looks like, or whether the headers are right.

If checking the actual email is the point of the test, you need somewhere that runs a real wp_mail(). On SandyWP that is what the Email Log does: mail is intercepted before it leaves, and you read the rendered HTML, recipient, headers, and attachments in the dashboard.

Is it really MySQL?

No. Playground uses SQLite, with a translation layer that presents it to WordPress as MySQL.

For ordinary WordPress work this is invisible and it works well. It stops being invisible when code goes near the database directly:

  • Hand-written $wpdb queries using MySQL-specific syntax or functions.
  • FULLTEXT indexes and MySQL full-text search.
  • Anything that inspects the schema, or a migration that issues raw ALTER TABLE.
  • Performance characteristics. SQLite and MariaDB behave differently under concurrent writes, so a query plan you profile here tells you nothing about production.

If your plugin ships raw SQL, Playground is testing the SQLite translation of it, not the thing your users run.

You can share a URL that boots a fresh Playground with your setup applied, using a Blueprint. You cannot share your site with your data in it.

The state lives in your browser, so a link to it means nothing to anyone else. Whoever opens the link gets their own empty instance, built from the same recipe.

For a demo that is often enough. For "here is the exact broken state, look at it", it is not.

What about speed?

Playground is fast to start compared to provisioning a server, but it is not instant, and the cost is paid on every load.

The limitations page gives the numbers: 5 to 10 seconds for fresh WordPress, 10 to 60 seconds or more once plugins are installed, with WASM assets of 15 to 30MB to download. Mobile devices run 1.5 to 2 times slower than desktop.

Then there are the smaller edges. Playground renders inside an iframe, so links with target="_top" reload the whole app, and JavaScript popups from within the iframe may not always display. WP-CLI works, but the docs state there is no definite list of supported commands, so you find out by trying.

What Playground is genuinely better at

We are not going to pretend otherwise. Playground wins outright on several things:

  • It is free and official, maintained inside the WordPress project.
  • It works offline. Nothing we run on servers can do that.
  • Nothing leaves your machine. For a first look at an unknown plugin, that is a real security property.
  • Zero signup, zero account, zero cost per site. You can boot fifty of them.
  • Blueprints are excellent. A JSON file that describes an environment, and a URL that builds it, is a genuinely good idea. We liked it enough that SandyWP supports Blueprints too.

If you are learning WordPress, giving a plugin a quick sniff test, or embedding a live WordPress in documentation, Playground is the right answer and a server is overkill.

When you need a real install instead

Move off Playground when the thing you are testing is one of the limits above:

  • The plugin talks to an external API, a licence server, or a payment provider.
  • You need to see the actual email that WordPress sent.
  • The code contains raw SQL, or you are testing a database migration.
  • Someone else has to open the exact site you are looking at.
  • You need SSH, WP-CLI without caveats, or a specific PHP version and php.ini.
  • The work has to still exist tomorrow.

A real install does not have to mean staging, and it should not mean touching production. A disposable sandbox on a server covers the gap: real MariaDB 11, real PHP, a real public URL, and a delete button.

That is what SandyWP is. Each sandbox is a container with a full Linux and PHP environment, an isolated database you can open in a browser-based manager and run SQL against, and PHP 7.4, 8.1, 8.2, or 8.3 switchable without touching a config file. Guest sandboxes expire after seven hours; account-owned ones run from one hour to permanent.

You can also SSH into one or mount it as a folder on your machine, which is the other thing a browser tab cannot do.

The honest framing is not "Playground or us". It is that most people need both: Playground for the quick look, a real disposable install for the moment the quick look stops being enough. If you want the feature-by-feature version, we keep one at WordPress Playground vs SandyWP.

Sources