
Dlaczego przenieśliśmy warstwę realtime Cliqer z Cloudflare (i dlaczego wciąż jesteśmy ich fanami)

24 września 2026 r. o 18:42 UTC przenieśliśmy wszystkie aktywne połączenia Cliqer z Cloudflare Workers i Durable Objects na nasze własne dedykowane serwery. Spróbowaliśmy edge'a i tym razem nas zawiódł. Jeśli korzystasz z Cliqer, w Twoim sposobie pracy nic się nie zmienia. Zmienia się to, co dzieje się pod spodem: Twoje pokoje nie restartują się już z powodów, których nikt nie potrafi wyjaśnić.
Ten wpis to szczera opowieść o tym, dlaczego. To także podziękowanie, bo nadal jesteśmy klientami Cloudflare i wciąż szczerze podziwiamy to, co budują.
- Przez cztery miesiące każdy pokój Cliqer działał na Cloudflare Durable Objects. Pomysł był piękny: każdy pokój dostaje własny, malutki, zawsze włączony serwer na edge'u.
- W praktyce pokoje Cliqer były restartowane bez naszego udziału, kilka razy dziennie, bez przekroczenia limitu pamięci, bez przekroczenia limitu CPU, bez błędu w naszym kodzie i bez żadnego wdrożenia. Każdy restart zrywał wszystkie połączenia w danym pokoju.
- Zbudowaliśmy około 18 różnych mechanizmów, żeby ukryć te restarty przed Tobą. Część z nich zadziałała. Sama złożoność zaczęła jednak powodować nowe błędy.
- Warstwa realtime Cliqer działa teraz na naszych własnych dedykowanych serwerach, nadal za siecią Cloudflare. Żadnych niespodziewanych restartów, żadnych resetów pamięci masowej, żadnej loterii lokalizacji.
- Jest też szybciej: testy startowe aplikacji desktopowej odpowiadają do 17 razy szybciej, a bezczynne połączenie otwiera się w 0,14 sekundy zamiast 1,2.
- Jeśli połączenie zostanie teraz zerwane, przyczyna jest znana: Twoja sieć, zaplanowana aktualizacja, po której łączysz się ponownie w około sekundę, albo siła wyższa. To już nie jest zagadka.
Co chcieliśmy zbudować
Cliqer to narzędzie do pracy na żywo. Prezenter stuka w telefon, a slajd przesuwa się na ekranie, który może znajdować się na innym kontynencie. Rozmówcy dołączają do transmisji, gospodarze przełączają źródła, timery odliczają czas na scenie. Wszystko to opiera się na WebSocketach: długotrwałych połączeniach, które nie mogą mrugnąć, bo jeśli mrugną, dzieje się to na oczach publiczności.
Durable Objects wyglądały na idealne rozwiązanie. Każdy pokój dostaje jednowątkowy obiekt, który utrzymuje własne sockety i własną pamięć masową, działając w sieci Cloudflare. Żadnych serwerów do zarządzania, żadnego skalowania do planowania. Pod koniec maja wszystkie pokoje działały już na nich, a w czerwcu dołączył do nich starszy most Cliqer v1.
Co poszło nie tak

Restarty, których nie potrafiliśmy wyjaśnić
Platforma może w każdej chwili zrestartować Durable Object, a gdy to robi, każdy WebSocket, który obiekt utrzymuje, zostaje zamknięty. W jednym 24-godzinnym oknie logów sprawdziliśmy właśnie to: żaden socket nie przetrwał restartu. Ani jeden.
Nie byłoby problemu, gdyby restarty zdarzały się rzadko. Tak jednak nie było:
- 21 restartów w 5 dni obiektu w Lizbonie, który obsługiwał wszystkie pokoje, w tym 4 w ciągu jednej godziny. Żadnego braku pamięci, żadnego limitu CPU, garść wewnętrznych błędów platformy i żadnego wdrożenia z naszej strony.
- Przenieśliśmy go. Durable Objects zostają tam, gdzie zostały pierwotnie utworzone, więc przeniesienie oznacza utworzenie obiektu od nowa i nadzieję, że trafi w lepsze miejsce. Pierwsza próba wylądowała w Madrycie, kolejna w Amsterdamie.
- W Amsterdamie restarty nie ustawały: co 2 do 16 godzin, średnio mniej więcej co 8,7 godziny.
- We wrześniu obiekt obsługujący starsze pokoje wciąż restartował się 2 do 5 razy dziennie, bez żadnego powodu. 8 września o 18:53 wszystkie starsze połączenia zostały zamknięte w tej samej milisekundzie. Bez wdrożenia, bez incydentu na stronie statusu.
Dla Ciebie każdy z nich oznaczał chwilę, w której pilot do prezentacji przestawał reagować, rozmówca znikał albo aplikacja informowała o ponownym łączeniu w samym środku wydarzenia.
Pamięć masowa, która przekraczała limit czasu i resetowała pokój
Między 7 a 10 września komunikat o błędzie „Durable Object storage operation exceeded timeout which caused object to be reset” pojawił się 8 razy w 4 obiektach. Jedna próba ponownego połączenia czekała 44,5 sekundy, zanim zakończyła się niepowodzeniem. Odczyt z pamięci masowej, który powinien trwać milisekundy, pociągnął za sobą cały pokój.
Każde wdrożenie restartowało każdy pokój
To akurat jest udokumentowane i uczciwe: wdrożenie nowej wersji Workera restartuje jego Durable Objects, a ich restart zamyka ich połączenia. Między 19 a 21 sierpnia 44% ponownych połączeń w aktywnych pokojach klientów przychodziło w zsynchronizowanych falach, a trzy nasze własne wydania jednego dnia zerwały wszystkie pokoje, jedno z nich w trakcie wydarzenia.
Wydzieliliśmy więc sockety do osobnego Workera i zbudowaliśmy narzędzie, które analizowało każdy zmieniony plik i decydowało, które wdrożenia mogą dotykać pokoi. To zadziałało: kolejne wydanie strony poszło na produkcję przy pięciu aktywnych gospodarzach i zerowej liczbie zdarzeń w pokojach. Oznaczało to jednak również, że każda zmiana w kodzie realtime nadal restartowała wszystkich.
Subtelne zachowania, które dały nam w kość podczas wydarzeń na żywo
- 16 minut ciszy. 4 sierpnia 43 sockety pozostawały połączone, a do żadnego pokoju nie dotarła ani jedna wiadomość. Edge dalej odpowiadał na heartbeaty w imieniu pokoju, więc żaden klient nie wiedział, że coś jest nie tak, i nikt nie połączył się ponownie. Wynikało to z funkcji platformy, którą właśnie wdrożyliśmy, w połączeniu z naszym własnym śledzeniem stanu. Wycofaliśmy ją w tym samym tygodniu.
- Gospodarze widma. Nie ma gwarancji, że zdarzenia zamknięcia dotrą do uśpionego obiektu, więc gospodarz, który już wyszedł, mógł wyglądać na połączonego przez wiele godzin.
- Adres URL zablokowany w cache'u na cztery godziny. W sierpniu warstwa cache przed naszym Workerem zawiesiła się na jedynym adresie URL, który aplikacja desktopowa sprawdza przy starcie. Aplikacja nie mogła się uruchomić. Ten sam URL z przypadkowym parametrem odpowiadał w sekundę.
Co zbudowaliśmy, żeby sobie poradzić
Przez te cztery miesiące zbudowaliśmy około 18 osobnych mechanizmów, żeby ukryć przed Tobą platformę: szybsze heartbeaty, czyszczenie gospodarzy widm, rejestry odbudowywane z pamięci masowej przy każdym wybudzeniu, tożsamości przetrwające restart, żeby Twoje aplikacje mogły wznowić pracę, osobny Worker do socketów, klasyfikator wdrożeń obejmujący 161 plików, ponowne losowanie lokalizacji, watchdog relayów, sharding pokoi i towarzyszący mu rejestr miejsc między shardami.
Trzy z nich później usunęliśmy, bo sprawiały więcej kłopotów, niż rozwiązywały. A każde obejście dokładało kolejne ruchome części. Rozdzielenie pokoi między obiekty dało nam zbuntowany pokój, który odpowiadał za niewłaściwy shard, widza uwięzionego w pętli przenoszenia i limit miejsc, który dało się obejść między shardami. Każdy z tych problemów naprawiliśmy, ale zamiast budować Cliqer, spędzaliśmy czas na obchodzeniu platformy.
Uczciwie mówiąc
Nie każde zerwane połączenie w tych miesiącach było winą Cloudflare. Sprawdziliśmy to:
- 86% pojedynczych ponownych połączeń dotyczyło pojedynczych urządzeń rozłączonych przez ich własną sieć: firmowe proxy, Wi-Fi w obiektach, firewalle, które nie lubią długich połączeń. Dlatego w sierpniu wprowadziliśmy w aplikacji desktopowej obsługę sieci firmowych.
- Część fal wywołały nasze własne wdrożenia, a kilka nasze własne narzędzia do debugowania.
- Nigdy nie zgłosiliśmy problemu z restartami do supportu. To nasza wina.
Durable Objects to znakomity kawałek inżynierii i do wielu zastosowań nadają się idealnie. Pokój, który nigdy nie może mrugnąć, przed publicznością na żywo, okazał się najgorszym możliwym przypadkiem dla platformy, która może go zrestartować w dowolnej chwili. Spróbowaliśmy edge'a dla realtime i tym razem nas zawiódł. To werdykt dotyczący tego konkretnego obciążenia, a nie edge'a jako takiego.
Co teraz obsługuje Twoje pokoje

Warstwa realtime Cliqer działa teraz na naszych własnych dedykowanych serwerach. Obsługują one stronę, API i każdy WebSocket oraz bezpośrednio utrzymują każdy pokój, wspierane przez lokalną bazę danych. Ruch nadal przechodzi przez sieć Cloudflare, więc zachowujesz tę samą ochronę i te same adresy.
Co zniknęło:
- Żadnych restartów bez naszej wiedzy. Proces działa, dopóki sami nie zdecydujemy inaczej.
- Żadnej loterii lokalizacji i żadnych przekroczeń limitu czasu pamięci masowej resetujących pokoje.
- Żadnego shardingu. Jeden pokój, jedno miejsce, jedno źródło prawdy.
O czym mówimy uczciwie:
- Gdy wdrażamy aktualizację, Twoje połączenie łączy się ponownie jeden raz. Nowa wersja uruchamia się obok starej i przejmuje ruch niemal natychmiast. Twoje aplikacje łączą się ponownie w około sekundę z tą samą tożsamością i kontynuują tam, gdzie były. Podczas naszej próby generalnej 4757 żądań webowych przeszło przez przełączenie i żadne nie zakończyło się błędem.
- Nasze serwery stoją w Europie. Wolimy utrzymywać maszyny, które w pełni rozumiemy, niż setki miejsc, do których nie mamy wglądu.
Do tego szybciej
Po naszej stronie logujemy czas trwania każdego żądania API, więc możemy porównać tydzień przed przeprowadzką z dniami po niej na prawdziwym ruchu, a nie w teście laboratoryjnym.
17x
szybsze sprawdzanie interfejsu w aplikacji desktopowej
10x
szybsze sprawdzanie nowych wydań
0.14 s
na otwarcie bezczynnego połączenia, wcześniej 1,2 s
4x
szybsze statystyki pulpitu zespołu
| Co robi aplikacja | Przed (mediana) | Po (mediana) | Ile razy szybciej |
|---|---|---|---|
| Aplikacja desktopowa sprawdza aktualizację interfejsu | 178 ms | 10 ms | 17x |
| Aplikacja desktopowa sprawdza, czy jest nowe wydanie | 344 ms | 32 ms | 10x |
| Pobieranie danych uwierzytelniających relaya dla wideo | 210 ms | 56 ms | 3,8x |
| Ładowanie statystyk pulpitu Twojego zespołu | 973 ms | 240 ms | 4x |
| Sprawdzanie Twojej licencji i planu | 268 ms | 119 ms | 2,3x |
Najwolniejsze żądania poprawiły się jeszcze bardziej. Najgorsze co dziesiąte ładowanie brandingu pulpitu skróciło się z 1,7 sekundy do niecałej połowy sekundy, a najgorsze pobrania danych uwierzytelniających relaya przyspieszyły 7-krotnie.
Największą zmianę odczujesz jako pierwszą. Połączenie realtime, które na starej platformie pozostawało bezczynne, otwierało się około 1,2 sekundy, bo musiało się najpierw wybudzić. Na naszym własnym serwerze otwiera się w około 0,14 sekundy, za każdym razem. Nasz niezależny monitor dostępności, który co minutę sprawdza cliqer.io z Ameryki Północnej, pokazuje to samo: około 750 ms na test przed przeprowadzką, około 380 ms po niej.
W samym pokoju kliknięcia już wcześniej były szybkie i nadal są. Zmieniło się wszystko wokół nich: otwieranie aplikacji, ładowanie strony prezentera, pobieranie danych Twojego konta. Wszystko odpowiada szybciej i za każdym razem tak samo.
Co Cloudflare nadal dla nas robi
Sporo, i to z przyjemnością:
DNS
Dla każdej domeny Cliqer.
Proxy, CDN i firewall
Przed cliqer.io, łącznie z WebSocketami, przy czym do naszych serwerów ma dostęp wyłącznie edge Cloudflare.
To dzięki ich narzędziom do obserwowalności i analityki możliwa była większość diagnozy opisanej w tym wpisie. Nadal jesteśmy ich klientami i nadal ich polecamy.
Opóźnienie pilota do prezentacji: dlaczego liczą się milisekundy
Co naprawdę dzieje się między Twoim stuknięciem a przesunięciem slajdu.
Jak przyspieszyliśmy udostępnianie ekranu czterokrotnie
Druga duża historia o wydajności z tego lata.
Jeśli coś się rozłączy, daj nam znać
Nasza obietnica jest prosta: gdy połączenie zostanie teraz zerwane, istnieje przyczyna, którą potrafimy znaleźć. Jeśli kiedykolwiek zobaczysz, że Cliqer łączy się ponownie w trakcie wydarzenia (a tutaj znajdziesz, co zrobić, gdy slajdy się zawieszą w takiej chwili), odpowiedz na dowolnego naszego maila albo otwórz czat w aplikacji. Czytamy każdą wiadomość i teraz naprawdę możemy Ci powiedzieć, dlaczego tak się stało.
Zdalne sterowanie Prezi i LibreOffice Impress
Jak skonfigurować niezawodne zdalne sterowanie zoomowanym płótnem Prezi i LibreOffice Impress z dowolnego telefonu na sali.
Dlaczego wyrzuciliśmy naszą aplikację we Flutterze i zbudowaliśmy Cliqer Remote od nowa natywnie, na rdzeniu w Rust
Zbudowaliśmy Cliqer Remote we Flutterze, zmierzyliśmy go na prawdziwym telefonie, a potem przebudowaliśmy natywnie na jednym rdzeniu w Rust: o połowę mniejsze zużycie baterii, zero nagrzewania. Liczby i wnioski.
Poprowadź swoje następne show z Cliqer
Czytaj dalej
Więcej: nowości produktowe na Twoje następne show


Dlaczego wyrzuciliśmy naszą aplikację we Flutterze i zbudowaliśmy Cliqer Remote od nowa natywnie, na rdzeniu w Rust

Jak przyspieszyliśmy udostępnianie ekranu czterokrotnie
Otrzymaj kolejny poradnik przed swoim następnym show
Praktyczne poradniki dla prezenterów, ekip AV i zespołów eventowych oraz wydania Cliqer, które mają znaczenie. Bez spamu, rezygnacja jednym kliknięciem.