Skip to content
Headless / custom / advanced WP

How to Add Real-Time Features to a WordPress Site Without Rewriting It

Can WordPress do real-time? Yes. How to add live updates with Pusher, Ably or SSE without breaking the page cache, and when real-time actually pays off.

By WitsCode9 min read
Headless / custom / advanced WP

Can a WordPress site do real-time, and if so, how? The short answer is yes, it can, and you do not need to throw away your site or rebuild it as a single-page application to get there. What you cannot do is expect WordPress to hold a live connection open by itself, because that is not how PHP works. The practical answer in 2026 is to keep WordPress doing what it is good at, managing content and firing events when something changes, and hand the live-connection job to a layer that is actually built for it.

That layer is usually a hosted service such as Pusher, Ably, or Supabase Realtime, or, for simpler one-way updates, the browser's own Server-Sent Events. WordPress publishes an event, the connection layer pushes it to every browser that is listening, and a small amount of JavaScript updates the page in front of the visitor. Done this way, real-time becomes a feature you bolt onto an existing site rather than a reason to rewrite it. The rest of this article explains why the native stack cannot do the job alone, the pattern that works, the lighter alternative, the one rule that stops real-time from wrecking your performance, and the cases where it is genuinely worth the effort.

Why WordPress and PHP cannot hold a connection open

To understand the right approach you have to understand the limitation, and the limitation is structural rather than a missing feature someone could add in a plugin.

WordPress runs on PHP, and PHP uses a request-and-response model. A request arrives, PHP boots WordPress, builds a response, sends it, and then the process is finished and handed back to the pool to serve the next visitor. Nothing persists between requests. This model is exactly why WordPress scales well for ordinary page traffic, because a worker is only busy for the fraction of a second it takes to build one page.

A real-time connection asks for the opposite behaviour. A WebSocket, the technology behind most live features, needs a process to stay alive and hold a network connection open for the entire time a visitor has the page open, which might be minutes or hours. PHP-FPM, the engine serving WordPress on almost every host, runs a fixed pool of worker processes, often somewhere between twenty and fifty. If each connected visitor occupied one worker for the length of their visit, fifty visitors would consume every worker in the pool and the site would stop serving normal pages entirely. The architecture simply does not have room for it.

WebSocket servers solve this with an event-loop runtime, the kind of thing Node.js, Go, or Erlang provide, which can juggle thousands of open connections across a handful of threads. Standard WordPress hosting does not include that runtime. WordPress does ship a Heartbeat API, but it is polling, not pushing. It asks the server for updates every fifteen to sixty seconds, and every one of those checks boots WordPress again. It is fine for the autosave indicator in the editor and far too heavy and too slow to call real-time. So the honest position is this: the limitation is real, and the answer is not to fight it but to route around it.

The pattern that works: WordPress publishes, a service connects

The pattern that works in 2026 splits the job into three clear roles, and once you see the split the whole thing stops feeling complicated.

WordPress is the publisher. It remains the source of truth for your content and your data, and when something changes it fires an event. You hook into an action that already exists, a post being saved, a WooCommerce order changing status, a comment being posted, or a custom action of your own, and from inside that hook you make a quick server-to-server call to a realtime service to announce what happened.

The realtime service is the connection layer. It holds the persistent connections to every visitor's browser, because that is the one thing it is engineered to do well. The browser is the subscriber. A small piece of JavaScript opens a single connection to that service, listens on a named channel, and updates the page when an event arrives. WordPress never talks to the browser directly for live updates, and the browser never waits on PHP.

In practice a Pusher integration on the WordPress side is only a few lines inside a hook you already understand:

add_action( 'woocommerce_order_status_changed', function ( $order_id ) {
    $pusher = new Pusher\Pusher(
        PUSHER_KEY, PUSHER_SECRET, PUSHER_APP_ID,
        [ 'cluster' => 'eu', 'useTLS' => true ]
    );
    // Publish to a named channel. Browsers listening get it instantly.
    $pusher->trigger( 'orders', 'status-changed', [
        'order_id' => $order_id,
        'status'   => wc_get_order( $order_id )->get_status(),
    ] );
} );

On the page itself, the browser subscribes and updates the DOM:

const pusher = new Pusher(PUSHER_PUBLIC_KEY, { cluster: 'eu' });
const channel = pusher.subscribe('orders');
channel.bind('status-changed', (data) => {
  document.querySelector(`#order-${data.order_id} .status`)
          .textContent = data.status;
});

The choice between Pusher, Ably, and Supabase Realtime is mostly about fit. Pusher is the simplest to start with and well documented, with a free tier that comfortably covers a small site. Ably does more, including message history so a browser that reconnects can replay anything it missed, which matters when a dropped message would be a real problem. Supabase Realtime is the natural pick when a project already uses Supabase or runs a headless front end, because it can stream database changes directly. All three follow the same pattern, so the integration shape on the WordPress side barely changes. One security note worth stating plainly: only the public application key ever goes into front-end JavaScript. The secret key stays server-side, in an environment variable or wp-config, and never reaches the browser.

Server-Sent Events: the lighter option

Not every real-time feature needs a hosted service or a two-way connection. When updates only ever flow in one direction, from the server out to the browser, Server-Sent Events are a lighter answer that costs nothing and adds no third-party dependency.

Server-Sent Events use the browser's built-in EventSource API. The browser opens one long-lived HTTP connection and the server streams plain text events down it as they happen. There is no library to load, no account to create, and reconnection is handled automatically by the browser, which even tells the server the ID of the last event it saw so the stream can resume cleanly. For a live notification feed, a status indicator, a progress bar, or a counter that only ever ticks upward, that is often all you need.

The catch is the same constraint from earlier in a new outfit. A Server-Sent Events endpoint that lives inside WordPress still holds a PHP worker open for as long as the connection lasts, so it has the identical worker-exhaustion problem as a raw WebSocket would. That makes a WordPress-hosted Server-Sent Events endpoint fine for low concurrency, an internal admin dashboard or an operations screen used by a handful of staff, and a poor idea for thousands of simultaneous public visitors. Serious deployments put the streaming endpoint on a small separate process rather than the main PHP-FPM pool, and they run over HTTP/2 so the browser is not limited to six connections per domain. Used within those limits, Server-Sent Events are an elegant, dependency-free way to add live updates to the parts of a site where the audience is small and the data only travels one way.

The cache-safety rule that protects your performance

This is the part that quietly decides whether your real-time feature makes the site better or worse, and it is the part most tutorials skip.

A WordPress front end in 2026 is almost always behind full-page caching. A caching plugin, the host's own page cache, a CDN edge, or all three, store the finished HTML and serve it to visitors without booting PHP at all. That is the single biggest reason a WordPress site feels fast.

Here is the trap. When live data changes, the tempting instinct is to purge the page cache so visitors see the fresh value. Do that on every real-time event and you have destroyed the cache. Every event becomes a cache miss, every cache miss is a full PHP render, and at any meaningful event volume your cache hit rate collapses. The site gets slower the more real-time you make it, which is the opposite of the intention.

The rule is simple to state and should never be broken: real-time updates happen client-side, after the cached page has loaded, and a real-time event must never invalidate the page cache. The cached HTML ships a sensible baseline value, the number of seats free at the moment the page was cached, for example, inside an element with an ID or data attribute. Then the realtime JavaScript connects and overwrites that element live.

<!-- Cached HTML carries a baseline. JS owns the live value after load. -->
<span id="seats-left" data-event="A12">12 seats left</span>

The cached page is just the first paint. The realtime layer is the source of truth for the live value. The page cache is never touched per event, the hit rate stays high, and the site stays fast while still feeling live. Anything personal to one visitor, such as their own notifications, should never be baked into a shared cached page in the first place and must always be fetched client-side after load.

When real-time is genuinely worth it

Real-time is not free. It adds a service, a dependency, and JavaScript to maintain, so it earns its place only where stale data actually costs the user or the business something.

It pays off clearly for live booking and availability, where seats, rooms, or appointment slots need to reflect reality so two people do not claim the last one. It pays off for notifications, where order updates, messages, and alerts are something users now simply expect rather than wait for. It pays off for live chat and support, which are two-way by nature and the textbook case for a hosted WebSocket service. And it pays off for auctions and bidding, where every watcher must see the current price the instant it changes or the experience is broken and unfair.

Where it does not pay off is the ordinary content site. A blog, a brochure site, or a page whose data changes hourly rather than by the second gains nothing from a live connection except cost and complexity. The test is honest and quick: would a visitor notice, or a sale be lost, if this number were a minute out of date? If the answer is no, polling or a normal page load is the right tool and real-time is over-engineering.

Building it without the rewrite

The throughline of all of this is that adding real-time to WordPress is an integration job, not a rebuild. WordPress keeps managing content and firing events, a connection layer does the part PHP cannot, JavaScript updates the page, and the cache rule keeps performance intact. The existing site stays exactly as it is.

That is the kind of work we do at WitsCode. We add live booking availability, notifications, bidding, and chat to WordPress sites as a focused custom build, choosing Pusher, Ably, Supabase Realtime, or Server-Sent Events to match the use case, wiring the publish side into the right hooks, and making sure every live update happens client-side so the page cache is never compromised. The result is a site that feels modern and responsive without losing the speed, the stability, or the WordPress admin your team already knows.

If you have a feature in mind that needs to update in front of the visitor, and you would rather add it cleanly than rebuild around it, that is exactly the build we can scope and deliver for you.

Get weekly field notes.

Practical writing on shipping products, straight to your inbox. No spam.

Need help with this?

WordPress Development

We design and build web apps, MVPs, and SaaS products. Talk to us about what you are working on.

Talk to us

Want to discuss headless / custom / advanced wp for your business?

Start a project and we'll talk through where you are, what's working, and the highest-leverage moves for the next 90 days.