Why we moved Cliqer's realtime off Cloudflare (and why we're still fans)

Four months on Cloudflare’s edge: what broke, what we built to cope, and why Cliqer now runs on our own dedicated servers.

Cliqer Team

25 September 2026 · 9 min read

A dedicated server rack glowing mint in a dark data hall

On 24 September 2026 at 18:42 UTC we moved every live Cliqer connection off Cloudflare Workers and Durable Objects and onto our own dedicated servers. We tried the edge, and on this occasion it failed us. If you use Cliqer, nothing about how you work changes. What changes is what happens underneath: your rooms no longer restart for reasons nobody can explain.

This post is the honest version of why. It is also a thank you, because we are still Cloudflare customers and still genuine fans of what they build.

Key takeaways
  • For four months, every Cliqer room ran on Cloudflare Durable Objects. The idea was beautiful: every room gets its own tiny, always-on server at the edge.
  • In practice, Cliqer's rooms were being restarted underneath us, several times a day, with no memory limit hit, no CPU limit hit, no error in our code and no deploy. Every restart dropped every connection in that room.
  • We built around 18 different mechanisms to hide those restarts from you. Some worked. The complexity itself started causing new bugs.
  • Cliqer's realtime now runs on our own dedicated servers, still behind Cloudflare's network. No surprise restarts, no storage resets, no placement lottery.
  • It is faster too: the desktop app's startup checks answer up to 17 times faster, and an idle connection opens in 0.14 seconds instead of 1.2.
  • If a connection drops now, the cause is known: your network, a planned update that reconnects you in about a second, or an act of God. It is no longer a mystery.

What we were trying to build

Cliqer is a live tool. A presenter taps their phone, and a slide moves on a screen that might be on another continent. Callers join a show, hosts switch sources, timers count down on stage. All of that rides on WebSockets: long-lived connections that must not blink, because when they do, it happens in front of an audience.

Durable Objects looked like the perfect fit. Each room gets a single-threaded object that holds its own sockets and its own storage, running on Cloudflare's network. No servers to manage, no scaling to plan. By late May every room was running on them, and the legacy Cliqer v1 bridge joined in June.

What went wrong

Restarts we could not explain

A Durable Object can be restarted by the platform at any time, and when it restarts, every WebSocket it holds is closed. In one 24-hour window of logs we checked specifically for this: zero sockets survived a restart. Not one.

That would be fine if restarts were rare. They were not:

  • 21 restarts in 5 days for the object in Lisbon that held every room, 4 of them in a single hour. No out-of-memory, no CPU limit, a handful of platform-internal errors, and no deploy from us.
  • We moved it. Durable Objects stay where they are first created, so moving means recreating it and hoping it lands somewhere better. The first attempt landed in Madrid, the next in Amsterdam.
  • In Amsterdam the restarts kept coming, every 2 to 16 hours, about every 8.7 hours on average.
  • In September, the object that served legacy rooms was still restarting 2 to 5 times a day, unprompted. On 8 September at 18:53 every legacy connection closed within the same millisecond. No deploy, no incident on the status page.

For you, each of those was a moment where the clicker stopped responding, a caller vanished, or the app said it was reconnecting in the middle of a show.

Storage that timed out and reset the room

Between 7 and 10 September we saw the error message "Durable Object storage operation exceeded timeout which caused object to be reset" 8 times across 4 objects. One reconnect attempt waited 44.5 seconds before it failed. A storage read that should take milliseconds took the whole room down with it.

Every deploy restarted every room

This one is documented, and it's fair: shipping a new version of a Worker restarts its Durable Objects, and restarting them closes their connections. Between 19 and 21 August, 44% of reconnects in live customer rooms came in synchronised waves, and three of our own releases in one day dropped every room, one of them mid-show.

So we split sockets into their own Worker, and built a tool that looked at every changed file and decided which deploys were allowed to touch rooms. That worked: the next website release went out with five live hosts and zero room events. It also meant that any change to realtime code still restarted everyone.

Subtle behaviour that bit us in live shows

  • A 16-minute silence. On 4 August, 43 sockets stayed connected while zero messages were delivered to any room. The edge kept answering heartbeats on the room's behalf, so no client knew anything was wrong and nobody reconnected. This came from a platform feature we had just adopted, combined with our own bookkeeping. We reverted it the same week.
  • Ghost hosts. Close events are not guaranteed to reach a sleeping object, so a host who had left could look connected for hours.
  • A cached URL stuck for four hours. In August, a caching layer in front of our Worker got stuck on the one URL the desktop app checks at startup. The app could not boot. The same URL with a junk parameter answered in a second.

What we built to cope

Over those four months we built around 18 separate mechanisms to hide the platform from you: faster heartbeats, sweeps for ghost hosts, registries rebuilt from storage on every wake, identities that survive a restart so your apps can resume, a separate socket Worker, a deploy classifier covering 161 files, placement re-rolls, a relay watchdog, per-room sharding and a cross-shard seat ledger to go with it.

Three of those we later deleted because they caused more trouble than they solved. And every workaround added moving parts. Sharding rooms across objects gave us a rogue room that answered for the wrong shard, a viewer stuck in a relocate loop, and a seat limit that could be bypassed across shards. Each one got fixed, but we were spending our time engineering around the platform instead of building Cliqer.

Being fair about it

Not every dropped connection in those months was Cloudflare's. We checked:

  • 86% of individual reconnects were single devices dropped by their own network: corporate proxies, venue Wi-Fi, firewalls that dislike long connections. That's why we shipped corporate network support in the desktop app in August.
  • Some waves were our own deploys, and a few were caused by our own debugging tools.
  • We never opened a support ticket about the restarts. That's on us.

Durable Objects are a brilliant piece of engineering, and for many workloads they are exactly right. A room that must never blink, in front of a live audience, turned out to be the worst case for a platform that can restart it at any moment. We tried the edge for realtime, and on this occasion it failed us. That is a verdict on this workload, not on the edge.

What runs your rooms now

Cliqer's realtime now runs on our own dedicated servers. They serve the website, the API and every WebSocket, and hold every room directly, backed by a local database. Traffic still comes through Cloudflare's network, so you keep the same protection and the same addresses.

What went away:

  • No restarts from underneath us. The process runs until we decide otherwise.
  • No placement lottery, and no storage timeouts resetting rooms.
  • No sharding. One room, one place, one source of truth.

What we kept honest:

  • When we ship an update, your connection reconnects once. The new version starts next to the old one and takes over almost instantly. Your apps reconnect in about a second with the same identity and carry on where they were. In our rehearsal, 4,757 web requests went through the switchover and none failed.
  • Our servers are in Europe. We would rather run machines we fully understand than hundreds of places we cannot see into.

Faster, too

We log how long every API request takes on our side, so we can compare the week before the move with the days after it, using real traffic rather than a lab test.

What the app is doingBefore (median)After (median)Faster by
Desktop app checking for its interface update178 ms10 ms17x
Desktop app checking for a new release344 ms32 ms10x
Fetching relay credentials for video210 ms56 ms3.8x
Loading your team's dashboard stats973 ms240 ms4x
Checking your licence and plan268 ms119 ms2.3x

The slowest requests improved even more. The worst one in ten dashboard branding loads dropped from 1.7 seconds to under half a second, and the worst relay-credential fetches got 7 times faster.

The biggest change is the one you feel first. A realtime connection that had sat idle on the old platform took about 1.2 seconds to open while it woke up. On our own server it opens in about 0.14 seconds, every time. Our independent uptime monitor, which checks cliqer.io every minute from North America, tells the same story: about 750 ms per check before the move, about 380 ms after.

Inside a room, clicks were already quick and they still are. What changed is everything around them: opening the app, loading the presenter page, fetching your account. It all answers faster, and the same way every time.

What Cloudflare still does for us

A lot, and happily:

DNS

For every Cliqer domain.

Proxy, CDN and firewall

In front of cliqer.io, WebSockets included, with only Cloudflare's edge allowed to reach our servers.

TURN relays

They get your video through restrictive networks.

Custom domains for teams

Including the certificates, plus storage for the desktop app's updates.

Their observability and analytics also made most of the diagnosis in this post possible. We are still customers, and we still recommend them.

Clicker latency: why milliseconds matter

What really happens between your tap and the slide moving.

How we made screen sharing four times faster

The other big performance story from this summer.

Getting through corporate firewalls

Why most single-device drops are the network, and how Cliqer gets through.

Security and networking docs

Ports, relays and what your IT team needs to allow.

If something drops, tell us

Our promise is simple: when a connection drops now, there is a reason we can find. If you ever see Cliqer reconnect mid-show (and here is what to do when slides freeze in the moment), reply to any of our emails or open a chat from the app. We read every one, and now we can actually tell you why.

reliabilitywebsocketscloudflarededicated serversengineering

Written by the Cliqer Team

We build Cliqer, the internet presentation clicker used on stages, in classrooms and in boardrooms around the world.

Run your next show with Cliqer

Any slides, any phone, anywhere. The desktop app hosts the room, presenters just open a link.

Keep reading

More product news for your next show

A software engineer reviewing a video latency graph on a monitor in a dimly lit office
Product News

How We Made Screen Sharing Four Times Faster

The engineering story behind cutting Cliqer’s screen sharing latency from over two seconds to about half a second.
An agency producer setting up a branded event room on a laptop with a client logo visible on screen
Product News

Branded Presenter Rooms: Custom Domains and Logos for Agencies

How AV and event agencies run white label presenter rooms on their own domain, with their own logo, for every client.
Laptop showing a zooming presentation canvas with a presenter checking a phone nearby
Clickers & Remotes

Remote Control for Prezi and LibreOffice Impress

How to set up reliable remote control for Prezi’s zooming canvas and LibreOffice Impress, from any phone in the room.
Newsletter

Get the next guide before your next show

Practical guides for presenters, AV crews and event teams, plus the Cliqer releases that matter. No spam, one click to leave.