PlanetScale, czyli baza danych traktowana jak kod
Zmiana schematu bazy na produkcji to jedna z niewielu czynności, przy których doświadczeni programiści nadal wstrzymują oddech. Nie ma tu gałęzi, nie ma przeglądu zmian, nie ma cofnięcia jednym poleceniem. Jest polecenie, które albo przejdzie, albo zablokuje tabelę na dwadzieścia minut w środku dnia.
PlanetScale zbudowano wokół tezy, że baza powinna działać jak repozytorium kodu. Tworzysz gałąź, wprowadzasz w niej zmianę, zgłaszasz ją do przeglądu, a po zatwierdzeniu system wprowadza ją na produkcji bez blokowania tabeli. Jeśli coś pójdzie nie tak, cofasz jednym kliknięciem.
Dwa silniki pod jedną powłoką
Platforma zaczynała jako usługa MySQL i tym była znana. Od 2025 roku dostępny jest również wariant z Postgresem, i to zmienia obraz wyboru.
Wariant MySQL stoi na warstwie rozpraszającej zapytania, znanej z bardzo dużych wdrożeń. Daje dzielenie danych na fragmenty i skalowanie poziome, kosztem kilku ograniczeń, o których niżej.
Wariant Postgres powstał później, ma inną architekturę opartą na uzgadnianiu stanu między węzłami i lokalnych dyskach o wysokiej wydajności. Nie ma tam warstwy rozpraszającej, więc nie ma też jej ograniczeń.
Wspólny jest za to model pracy: gałęzie, zgłoszenia wdrożeniowe i przegląd zmian działają tak samo w obu wariantach. To znaczy, że wybór silnika sprowadza się do zwykłych pytań o zgodność z aplikacją, a nie do rezygnacji z tego, po co się tu przychodzi.
Praktyczna wskazówka przy nowym projekcie: jeśli nic nie przywiązuje Cię do MySQL, Postgres jest tu wygodniejszy, bo nie nakłada ograniczeń warstwy rozpraszającej i wchodzi taniej.
Gałęzie bazy w praktyce
To jest funkcja, dla której ludzie tu przychodzą, więc warto zobaczyć ją w działaniu.
pscale branch create sklep dodaj-rabaty
pscale shell sklep dodaj-rabatyGałąź powstaje jako kopia schematu produkcyjnego, bez kopiowania wszystkich danych. Tworzy się w kilka sekund, więc każdy programista może mieć własną, a każda gałąź kodu własną gałąź bazy.
ALTER TABLE zamowienia ADD COLUMN rabat DECIMAL(5,2) DEFAULT 0;
CREATE INDEX idx_rabat ON zamowienia (rabat);Po wprowadzeniu zmian zgłaszasz je do wdrożenia.
pscale deploy-request create sklep dodaj-rabatyZgłoszenie pokazuje różnicę schematu w formie czytelnej dla człowieka i ostrzega przed operacjami ryzykownymi. Po zatwierdzeniu zmiana idzie na produkcję w tle, przez mechanizm replikacji, a przełączenie następuje dopiero wtedy, gdy nowa struktura jest gotowa. Tabela nie jest blokowana, a w razie problemu dostępne jest cofnięcie.
To ostatnie zasługuje na podkreślenie, bo w klasycznym układzie cofnięcie migracji oznacza napisanie odwrotnej migracji i modlitwę, żeby dane w międzyczasie nie rozjechały się nieodwracalnie.
Czego nie da się zrobić w wariancie MySQL
Ta sekcja jest najważniejsza w całym tekście, bo dotyczy rzeczy, które odkrywa się zwykle po trzech tygodniach pracy.
Ograniczenia kluczy obcych działają inaczej niż w klasycznym MySQL i przez lata były po prostu niedostępne. Powód jest architektoniczny: przy danych rozproszonych po wielu węzłach wymuszenie powiązania między nimi jest kosztowne. Wsparcie się poprawiło, ale przed decyzją sprawdź, czy Twój schemat rzeczywiście działa w tym układzie.
Konsekwencja praktyczna jest taka, że spójność powiązań pilnuje aplikacja albo warstwa dostępu. Narzędzia takie jak Prisma czy Drizzle potrafią emulować to zachowanie, więc kod wygląda znajomo, natomiast baza nie zatrzyma zapisu naruszającego powiązanie.
Druga sprawa to zapytania łączące wiele tabel przy danych podzielonych na fragmenty. Działają, ale mogą wymagać pobrania danych z kilku węzłów, co bywa kosztowne. Przy projektowaniu schematu warto trzymać razem dane, o które pytasz razem.
Trzecia to długie transakcje. Środowisko jest zestrojone pod krótkie operacje, więc transakcja trzymana otwarta przez minuty jest tu antywzorcem.
W wariancie Postgres większość tych ograniczeń nie występuje, bo nie ma warstwy rozpraszającej. To jeden z powodów, dla których nowe projekty częściej wybierają dziś ten silnik.
Gałęzie w procesie zespołowym
Sama możliwość tworzenia gałęzi niewiele daje, dopóki nie wpięta jest w sposób pracy zespołu, i to jest część, którą trzeba przemyśleć samodzielnie.
Najprostszy działający układ wygląda tak. Gałąź bazy powstaje razem z gałęzią kodu i nosi tę samą nazwę, więc powiązanie jest oczywiste dla każdego. Zgłoszenie wdrożeniowe schematu tworzy się razem ze zgłoszeniem zmian w kodzie i przechodzi ten sam przegląd. Wdrożenie schematu następuje przed wdrożeniem kodu, bo nowa kolumna musi istnieć, zanim aplikacja zacznie ją zapisywać.
Ta ostatnia kolejność ma konsekwencję, o której łatwo zapomnieć. Zmiana usuwająca kolumnę musi iść odwrotnie: najpierw kod przestaje jej używać, potem kolumna znika. Zrobione w złej kolejności daje kilka minut błędów na produkcji, i to jest najczęstsza przyczyna nieudanego wdrożenia w tym modelu.
Środowisko testowe warto oprzeć na osobnej gałęzi długo żyjącej, a nie na produkcji. Wtedy testy końcowe działają na strukturze, która za chwilę trafi na produkcję, a nie na tej, która już tam jest.
Sprzątanie gałęzi najlepiej powiązać z zamknięciem zgłoszenia w repozytorium kodu. Ręczne usuwanie zawsze przegrywa z pamięcią zespołu, a nieużywane gałęzie zostają na miesiące i naliczają koszt.
Ceny i model rozliczeń
Darmowy próg został wycofany w 2024 roku i nie wrócił. To zmiana istotna, bo wiele materiałów w sieci nadal opisuje nieistniejącą wersję bezpłatną, a projekt zaczyna się tu od planu płatnego.
Najniższy plan zaczyna się od kilku dolarów miesięcznie za pojedynczy węzeł Postgresa. Wariant MySQL nie ma odpowiednika jednowęzłowego i występuje wyłącznie w układzie odpornym na awarie, czyli z trzema węzłami, więc jego najtańszy klaster kosztuje kilkadziesiąt dolarów miesięcznie, a nie kilka. Osobno dostępna jest rodzina planów na sprzęcie dedykowanym z dyskami o niskich opóźnieniach, zaczynająca się od pięćdziesięciu dolarów miesięcznie i przeznaczona dla obciążeń wrażliwych na czas odpowiedzi.
Rozliczenie idzie za zasoby węzła, a nie za liczbę zapytań, co ma dwie konsekwencje. Pierwsza jest przyjemna: rachunek nie skacze wraz z liczbą zapytań. Druga mniej: płacisz również wtedy, gdy baza stoi bezczynnie, więc do środowiska testowego uruchamianego raz w tygodniu to nie jest najtańszy wybór.
Sam węzeł to jednak nie cały rachunek i tu kryje się najczęstsze zaskoczenie. Osobno liczą się miejsce na dane ponad wliczone dziesięć gigabajtów przy dyskach sieciowych, kopie zapasowe oraz ruch wychodzący ponad wliczoną pulę, którą kalkulator cennika pokazuje jako sto gigabajtów miesięcznie, a powyżej niej stawkę sześciu centów za gigabajt. Aplikacja odsyłająca dużo danych na zewnątrz ma więc pozycję rosnącą wprost z ruchem, mimo że sam plan jest stały.
Gałęzie deweloperskie rozliczane są za czas istnienia, naliczany co do milisekundy. Gałąź zapomniana na miesiąc kosztuje przez cały ten miesiąc, i to jest powód, dla którego sprzątanie warto zautomatyzować, a nie zostawiać pamięci zespołu.
Ceny zmieniają się częściej niż dokumentacja, więc przed policzeniem budżetu na rok sprawdź aktualny cennik na stronie usługi. Policz też koszt środowisk pobocznych, bo przy trzech środowiskach i kilku gałęziach rachunek wygląda inaczej niż przy jednej bazie produkcyjnej.
Połączenia i praca z aplikacją
Warstwa połączeń wygląda tu zwyczajnie, natomiast dwie rzeczy różnią się na tyle, że warto je znać przed pierwszym wdrożeniem.
Pierwsza to szyfrowanie połączenia, które jest wymagane. Klient bez włączonego szyfrowania po prostu nie nawiąże sesji, a komunikat błędu bywa mylący i wskazuje na uwierzytelnianie zamiast na przyczynę.
const polaczenie = {
host: process.env.DB_HOST,
username: process.env.DB_USER,
password: process.env.DB_PASSWORD,
ssl: { rejectUnauthorized: true }
}Druga to liczba jednoczesnych połączeń przy wdrożeniu bezserwerowym. Każda instancja funkcji otwiera własne połączenie, więc przy nagłym ruchu limit potrafi zostać osiągnięty w kilka sekund. Rozwiązania są dwa: pośrednik zarządzający pulą połączeń albo sterownik komunikujący się przez protokół sieciowy zamiast klasycznego gniazda.
Ten drugi wariant wart jest uwagi zwłaszcza w środowiskach brzegowych, gdzie klasyczne połączenie z bazą nie jest w ogóle dostępne. Zapytanie idzie wtedy przez zwykłe żądanie sieciowe, co nakłada niewielki narzut, a otwiera możliwość uruchamiania logiki blisko użytkownika.
Poświadczenia dostępu warto wystawiać osobno dla każdego środowiska i każdej gałęzi, a nie współdzielić jednego kompletu. Odebranie dostępu jednemu środowisku bez naruszania pozostałych to wtedy jedno kliknięcie, a nie zmiana hasła w pięciu miejscach naraz.
Wydajność i wgląd w zapytania
Baza szybko przestaje być wąskim gardłem, gdy widać, które zapytania kosztują najwięcej, a właśnie ten wgląd bywa najsłabszą stroną własnych wdrożeń.
Wbudowany podgląd pokazuje zapytania pogrupowane po kształcie, razem z liczbą wywołań i czasem wykonania. To ustawienie domyślne, więc nie trzeba niczego konfigurować, żeby zobaczyć, że jedno zapytanie wykonuje się czterdzieści tysięcy razy na minutę.
Najczęstszym odkryciem przy pierwszym spojrzeniu jest zapytanie w pętli, powstałe przypadkiem z leniwego pobierania powiązań w warstwie dostępu. Wygląda niewinnie w kodzie, a generuje jedno zapytanie na każdy wiersz listy. Naprawa polega zwykle na jawnym dołączeniu powiązania w jednym zapytaniu.
Drugim jest brakujący indeks na kolumnie używanej do filtrowania. Przy tysiącu wierszy nikt tego nie zauważy, przy milionie różnica sięga sekund. Warto sprawdzić plan wykonania dla najczęstszych zapytań, zanim dane urosną.
Trzecim jest pobieranie wszystkich kolumn tam, gdzie potrzebne są dwie. Przy szerokich tabelach z polami tekstowymi to bywa różnica rzędu wielkości w ilości przesyłanych danych, a poprawka mieści się w jednej linii.
Warto wyrobić sobie nawyk zaglądania tam po każdym większym wdrożeniu, a nie dopiero wtedy, gdy strona zaczyna się wlec. Nowe zapytanie wykonujące się sto razy częściej, niż zakładał autor, widać w tym zestawieniu od razu, a po tygodniu ginie wśród reszty ruchu i wymaga znacznie dłuższego szukania.
PlanetScale kontra alternatywy
| Rozwiązanie | Mocna strona | Słabość | Kiedy wybrać |
|---|---|---|---|
| PlanetScale | Gałęzie, wdrożenia bez przestoju, skala | Brak darmowego progu, ograniczenia MySQL | Zespół często zmieniający schemat |
| Neon | Postgres z gałęziami, wstrzymywanie przy bezczynności | Zimny start po wstrzymaniu | Środowiska testowe i projekty poboczne |
| Supabase | Baza plus uwierzytelnianie, pliki i API | Więcej rzeczy do ogarnięcia | Aplikacja potrzebująca całego zaplecza |
| Baza u dostawcy chmury | Pełna kontrola, dojrzałość | Migracje i utrzymanie po Twojej stronie | Zespół z administratorem baz danych |
Wybór między pierwszym a drugim wierszem sprowadza się do modelu rozliczeń. Wstrzymywanie bazy przy braku ruchu jest ogromną zaletą przy środowiskach pobocznych i wadą przy usłudze, która musi odpowiedzieć natychmiast o trzeciej w nocy.
Trzeci wiersz to inna kategoria: nie sama baza, tylko zestaw usług wokół niej. Jeśli potrzebujesz wyłącznie bazy, dokładanie reszty jest nadmiarem.
Typowe błędy
Pierwszy to planowanie projektu w oparciu o darmowy próg. Został wycofany, więc koszt trzeba przewidzieć od pierwszego dnia.
Drugi to wybór wariantu MySQL bez sprawdzenia, czy schemat radzi sobie z ograniczeniami warstwy rozpraszającej. Przy nowym projekcie bez zaszłości Postgres jest zwykle prostszym wyborem.
Trzeci to zakładanie, że baza wymusi spójność powiązań. Jeśli robi to warstwa dostępu, a nie baza, zapis z pominięciem tej warstwy przejdzie bez sprzeciwu.
Czwarty to zmiana schematu z pominięciem zgłoszenia wdrożeniowego. Da się, a wtedy tracisz przegląd, wdrożenie w tle i możliwość cofnięcia, czyli wszystko, po co się tu przyszło.
Piąty to zapominanie o usuwaniu gałęzi. Powstają w sekundę i zostają na miesiące, a każda coś kosztuje.
Szósty to długie transakcje przeniesione żywcem z klasycznego wdrożenia. Środowisko jest zestrojone pod krótkie operacje i takich oczekuje, więc operację trwającą minuty lepiej rozbić na mniejsze kroki.
FAQ
Czy PlanetScale ma darmowy plan?
Nie. Darmowy próg został wycofany w 2024 roku i nie został przywrócony, mimo że wiele materiałów w sieci nadal o nim wspomina. Najniższy plan to kilka dolarów miesięcznie za pojedynczy węzeł, a aktualne stawki warto sprawdzić w cenniku.
MySQL czy Postgres?
Przy nowym projekcie bez zaszłości zwykle Postgres, bo nie nakłada ograniczeń warstwy rozpraszającej i wchodzi taniej. MySQL wybierz wtedy, gdy aplikacja już na nim stoi albo gdy potrzebujesz dzielenia danych na fragmenty przy bardzo dużej skali.
Czy gałąź bazy kopiuje dane?
Nie, gałąź powstaje jako kopia samego schematu, dlatego tworzy się w sekundy niezależnie od rozmiaru bazy. Dane produkcyjne można osobno przenieść do gałęzi, jeśli testy tego wymagają.
Czy działa z popularnymi warstwami dostępu do danych?
Tak, połączenie odbywa się standardowym protokołem, więc Prisma, Drizzle i inne narzędzia działają normalnie. Przy wariancie MySQL warto włączyć emulację powiązań, jeśli warstwa dostępu ją oferuje.
Czym różni się od bazy u dostawcy chmury?
Modelem pracy przy zmianach schematu. U dostawcy chmury dostajesz maszynę z bazą i migracje prowadzisz sam. Tutaj dostajesz gałęzie, przegląd zmian i wdrożenie w tle, co przy zespole często zmieniającym schemat jest realną różnicą w tempie pracy.
Dokumentacja stoi na stronie usługi, a warstwę leżącą pod wariantem MySQL opisuje projekt Vitess.