O czym jest ten film
- AI ułatwiła budowanie aplikacji, ale większość tego, co powstaje metodą „vibe codingu”, to prototypy, które sypią się przy kilku użytkownikach z braku projektu systemu.
- Projektowanie systemu w erze AI opiera się na warstwach abstrakcji (chmura → dostawcy infrastruktury typu Convex/Vercel), które zdejmują z twórcy większość ciężkiej pracy.
- Inżynieria to zawsze kompromisy: skalowalność, niezawodność, wydajność i koszt — nie istnieje system idealny.
- Autor pokazuje architekturę własnej aplikacji Pluto — agenta AI dla firm — od zera: stos, decyzje, struktura kodu i sposób pracy z AI.
- Fundamentem jest monorepo (Turborepo), w którym żyją wszystkie klienty (web, mobile, desktop, admin) i backend — dzięki temu agent AI ma dostęp do całego kodu.
- Żelazna zasada bezpieczeństwa: klient nigdy nie rozmawia bezpośrednio z bazą danych — zawsze przez serwer.
- Convex łączy backend i bazę danych w jednej infrastrukturze, oferując gotowe komponenty (workflow, workpool, integracje) i „wszystko jako kod”, co lubią agenty AI.
- Bardziej złożone, odseparowane fragmenty (inference/płatności oraz iMessage) autor wydzielił jako osobne serwisy na stosie Effect TS i Postgres.
- Pozostałe wybory narzędzi: WorkOS (uwierzytelnianie klasy enterprise), Autumn (płatności kredytowe), Daytona (sandboxy dla agentów), OpenRouter (inference), Sentry i PostHog (logowanie błędów i analityka).
- Głównym świadomym kompromisem Pluto jest koszt — autor stawia na niezawodność i szybkość, a optymalizację wydatków odkłada na później.
Redakcyjne tłumaczenie
Prototyp to jeszcze nie produkt
Budowanie aplikacji stało się dużo łatwiejsze dzięki AI. Bądźmy jednak szczerzy: kiedy mówię „aplikacje”, tak naprawdę mam na myśli prototypy. Niewiele z tego, co powstaje, to produkty naprawdę wysokiej jakości. Za każdym razem, gdy ktoś sklei aplikację metodą „na czuja”, wystarczy dziesięciu użytkowników i wszystko się wywraca. Dzieje się tak dlatego, że taka osoba nie umie projektować systemu. Z tego samego powodu programista korzystający z AI zbuduje solidniejszą aplikację niż ktoś, kto programistą nie jest.
I właśnie z tym pomoże dzisiejszy materiał. Pokażę wam, jak zaprojektować solidny system, gdy budujecie aplikacje z AI — w podejściu „agentic engineering”. Zrobię to, tłumacząc, jak od podstaw powstała moja aplikacja Pluto: wszystkie narzędzia, których używam, mój stos technologiczny, informacje, na których się opierałem, podjęte decyzje, sposób ułożenia kodu i to, jak korzystam z AI. Dosłownie pokażę wszystko. Jeśli planujesz zbudować aplikację, która trafi na produkcję i będzie realnie używana, musisz to obejrzeć. Nie pominę żadnego szczegółu.
Czym jest projektowanie systemu w erze AI
Zacznijmy od podstaw: co znaczy „projektowanie systemu”? Fikuśna definicja brzmi tak: to proces planowania architektury, komponentów, modułów, interfejsów i przepływu danych w systemie oprogramowania tak, by spełnić określone wymagania.
W dawnych czasach, przed AI, oglądaliśmy mnóstwo filmów właśnie po to, by nauczyć się projektować systemy. Trzeba było rozstrzygnąć, czego użyjesz do przechowywania danych, gdzie umieścisz load balancer, jakiej usługi użyjesz do alertów, jak będzie wyglądał twój pipeline CI/CD. O tym wszystkim musiał myśleć projektant systemu. Dziś, w erze AI, istnieje wiele narzędzi, które to abstrahują i sprawiają, że wdrożenie tych elementów jest znacznie prostsze.
(Informacja dodatkowa: load balancer to element rozdzielający ruch między serwery; CI/CD to zautomatyzowany proces budowania i wdrażania kodu).
Inżynieria to kompromisy
Jedną rzecz trzeba zrozumieć — niezależnie od tego, czy jesteś inżynierem, czy nie: inżynieria to przede wszystkim kompromisy. Nie istnieje coś takiego jak system doskonały. Nie ma systemu, który obsłuży każdy scenariusz i każdy przypadek. Wszystko ma swoje kompromisy: każdy stos, każde narzędzie, każdy dostawca infrastruktury. Nic nie jest idealne.
Projektując system, musimy więc rozważyć kilka rzeczy:
- Skalowalność — zdolność systemu do obsługi rosnącego ruchu lub ilości danych poprzez dodawanie zasobów. Jeśli aplikację zaleje ruch, czy wystarczy wejść na jakiś panel, dodać kilka serwerów i po sprawie? Czy może system skaluje się sam?
- Niezawodność — jakie jest prawdopodobieństwo, że system padnie? Czy dostawca, którego wybieramy, słynie z częstych awarii? To decyzja, którą trzeba wziąć pod uwagę.
- Wydajność — czy dane rozwiązanie pozwala aplikacji być szybką? Chcemy, żeby nasze aplikacje śmigały. Jeśli narzędzie albo sposób architektury spowalnia aplikację, to problem.
- Koszt — czy to nas zrujnuje? Ile realnie jesteśmy w stanie wydać?
To wszystko trzeba przemyśleć, bo inżynieria to gra kompromisów.
Krótka historia infrastruktury: od własnego żelaza do warstw abstrakcji
Zanim przejdę do projektu Pluto, chcę pokazać, jak to wszystko działa i jaka infrastruktura jest dostępna.
Kiedyś strony i aplikacje serwowano tak: firmy miały własne serwery, własne żelazo, szafy serwerowe w biurze. Było kilku informatyków, paru programistów, paru ludzi od DevOps — i to ty skalowałeś stronę własnymi rękami. Jeśli miałeś duży ruch, ale nie miałeś sprzętu, żeby go udźwignąć, byłeś ugotowany. A jeśli miałeś szafy pełne serwerów bez ruchu — właśnie przepaliłeś stos pieniędzy. To były czasy, gdy trzeba było wszystko precyzyjnie kalkulować: drogo, trudno przewidzieć, ciężko skalować.
Potem firmy takie jak Amazon, Google i Microsoft zbudowały własne chmury. Amazon stworzył AWS, Google — GCP, Microsoft — Azure, do tego doszedł Cloudflare. Kupili własne żelazo, rozmieścili je w różnych lokalizacjach i powiedzieli: będziemy dostawcą, u którego uruchomisz swoje aplikacje. Cudowne w AWS, GCP i Azure było to, że nie musiałem już zarządzać własnymi szafami serwerowymi ani zatrudniać informatyków, którzy coś tam wpinają. Mogłem po prostu wdrożyć aplikację prosto na AWS czy Azure. Oni mają całą masę usług i narzędzi, którymi sami zarządzają, i biorą na siebie żmudną, ciężką robotę. To wtedy sieć eksplodowała — strony, backendy, mnóstwo ciekawych rzeczy zaczęło się pojawiać.
I to właśnie nazywamy abstrakcją. Może brzmi jak wielkie inżynierskie słowo, ale jeśli chcesz zbudować coś fajnego, słuchaj uważnie. Abstrakcja w informatyce to proces ukrywania złożonych szczegółów implementacyjnych i skupiania się wyłącznie na istotnych, wysokopoziomowych cechach obiektu lub systemu. AWS, GCP, Azure i Cloudflare zabstrahowały moją potrzebę posiadania fizycznego serwera oraz konfigurowania oprogramowania, które ma na nim działać. Zdjęli to ze mnie.
Z czasem pojawiła się kolejna warstwa abstrakcji: Convex, Vercel, Supabase, Neon i wiele innych firm. I zaznaczę — gdyby oglądał to ktoś z tych firm — tak, Vercel ma na przykład własne żelazo, chyba Planet Scale też. Ale hipotetycznie: Vercel na starcie „owijał” AWS, GCP albo któregoś z tych gigantów. Convex podobnie. Ta warstwa abstrakcji sprawiła, że korzystanie z tych narzędzi stało się dużo łatwiejsze — bo nie wiem, ilu z was używało AWS. AWS jeszcze ujdzie. Ale GCP i Azure są okropne w obsłudze. Mam certyfikat z Azure i powiem wam: Azure to koszmar. Nie znam nikogo, kto potrafiłby wdrożyć aplikację w Reakcie na Azure w mniej niż pięć minut. To jest aż tak pokręcone.
Dlatego mamy narzędzia i dostawców infrastruktury jak Convex, Vercel czy Supabase, którzy „owijają” i abstrahują AWS, GCP, Azure i Cloudflare. Ta warstwa zasadniczo umożliwiła nam — tobie i mnie — budowanie aplikacji. Ja nie wdrażam na AWS, GCP ani Azure. Czasem używam Cloudflare, ale w większości przypadków korzystam z Vercela. Do backendu używam Convexa. Jeśli potrzebuję bazy Postgres, sięgam po Planet Scale. Nie muszę już schodzić na te niższe poziomy abstrakcji.
Podsumowując, jak jest dziś: wciąż są ludzie, którzy używają własnego żelaza — nie polecam. Są firmy, które świadczą tę usługę za ciebie, jak AWS czy GCP — bardzo potężne, ale doświadczenie programisty (a raczej doświadczenie agenta) jest fatalne. I są narzędzia jak Convex czy Vercel — świetne w obsłudze, łatwo się skalują i wykonują za ciebie mnóstwo trudnej pracy, o którą nie musisz się martwić.
Pluto — wymagania na starcie
Przejdźmy do Pluto. Przy jego budowie kilka rzeczy było ciekawych.
Po pierwsze, potrzebowałem uwierzytelniania, z którego mogą korzystać firmy — takiego „poważnego” logowania. Potrzebowałem obsługi klientów, którzy być może chcą zgodności z SOC 2 i podobnych rzeczy. (Informacja dodatkowa: SOC 2 to standard audytu bezpieczeństwa danych, ważny przy sprzedaży oprogramowania firmom). Uwierzytelnianie było więc kwestią do przemyślenia.
Wiedziałem też, że część osób użyje tego prywatnie, ale będą też firmy. A jeśli używa tego firma, to może menedżer wszystko konfiguruje, zaprasza pracowników i dopiero oni to uruchamiają. Do tego dochodzi rozliczanie. Jaki model płatności chcę? Subskrypcję? Ludzie już płacą za subskrypcje i mają ich chyba dość. Może zrobimy system kredytowy, w którym po prostu doładowujesz konto i płacisz za zużycie? To też trzeba zbudować.
Kolejna sprawa: to jest agent. Muszę więc pomyśleć, gdzie go wdrożę. Miejsce wdrożenia powinno być względnie tanie, ale musi też dać się skalować i nie może padać — musi być niezawodne. To wszystko rozważałem, planując Pluto.
Cztery klienty i jedno monorepo
Pluto ma cztery powierzchnie klienckie: aplikację webową, aplikację desktopową, aplikację mobilną (mobilna powstała w ramach jednego przebiegu Fable) oraz wewnętrzny panel administracyjny.
Budując aplikację, trzeba myśleć o trzech rzeczach: kliencie, serwerze i bazie danych. Klient to miejsce, w którym ludzie wchodzą w interakcję z aplikacją — strona, aplikacja mobilna albo desktopowa. Ważne, żeby wybierać narzędzie, które się zna. W moim przypadku do aplikacji webowych używam SvelteKit. SvelteKit to w zasadzie odpowiednik Next.js dla Svelte. Uwielbiam go: jest minimalistyczny, szybki, łatwo zbudować w nim wydajne strony.
Ale co, jeśli chcę aplikację mobilną? Mogę zbudować natywną apkę na macOS, ale jeśli chcę też Androida, sięgam po Expo i React Native. A jeśli chcę aplikację desktopową, używam Electrona i po prostu „owijam” nim stronę.
Mam więc aplikację webową, mobilną i desktopową. Czy mam prowadzić trzy różne projekty w trzech różnych repozytoriach? Jak tym zarządzać? Poznajcie naszego dobrego przyjaciela: monorepo. Monorepo to jedno wielkie repozytorium kodu, w którym mogą żyć różne części aplikacji. Mam w nim aplikację webową, mobilną, desktopową, a także backend. Wszystkie te klienty komunikują się z tym samym backendem.
Dlaczego trzymanie wszystkiego w jednej bazie kodu jest fajne? Bo kiedy używam agenta AI — w tym przypadku Fable 5, który wrócił do gry — agent ma dostęp do całego kodu, mimo że mam osobno aplikację webową, desktopową i mobilną. Gdybym miał trzy osobne repozytoria, powstałyby oddzielone konteksty i mnie, człowiekowi, byłoby trudno tym zarządzać. A jeśli ktoś w ogóle nie umie kodować — powodzenia, to będzie ciężka przeprawa.
Dlatego niemal zawsze zaczynam od monorepo. Ponieważ do wdrożeń używam Vercela, korzystam z Turborepo. Tak układam swoje aplikacje. Monorepo pozwala mi mieć wiele klientów i jeden wspólny backend. Mogę mieć nawet jedną bibliotekę komponentów, jedną bibliotekę UI, współdzieloną przez wszystkie klienty. Do aplikacji webowej używam Svelte, do mobilnej — jeśli nie potrzebuję Androida, lubię Swift, ale zwykle stawiam na Expo i React Native — a do desktopu Electron.
Serwer i baza danych: żelazna zasada bezpieczeństwa
Teraz muszę pomyśleć o serwerze i bazie danych. Jeśli macie wrażenie, że to zalew informacji — spokojnie, na koniec wszystko poskładam w całość. Słuchajcie i notujcie.
Mój serwer musi pozwalać na odczyt danych z bazy, zapis danych do bazy i na interakcję z usługami zewnętrznymi — na przykład wywołanie API pogodowego. Chcę też mieć pewność, że te operacje nie zawodzą i nie są wolne.
I teraz najważniejsze: nigdy, przenigdy nie odczytuj danych bezpośrednio z klienta do bazy. Klient nigdy nie powinien rozmawiać z bazą danych. To jeden z głównych powodów, dla których nie przepadam za Supabase. Owszem, Supabase ma bibliotekę serwerową, więc można tego uniknąć, ale większość ludzi tego nie robi — zamiast tego konfigurują RLS. Dla mnie to gra pozorów.
(Informacja dodatkowa: RLS, czyli Row-Level Security, to mechanizm bazy danych ograniczający dostęp do poszczególnych wierszy — pozwala klientowi łączyć się z bazą „bezpiecznie”, ale autor uważa to za ryzykowne).
Prawdziwy system działa tak: klient woła serwer, serwer woła bazę, baza odpowiada serwerowi, a serwer przekazuje odpowiedź klientowi. To jest bezpieczne. Jeśli klient rozmawia bezpośrednio z bazą, ktoś może otworzyć podgląd elementu, wejść w zakładkę „Sieć”, podejrzeć zapytania, odczytać twój klucz API — i jesteś ugotowany.
Kiedyś (a właściwie wielu ludzi robi tak do dziś) budowało się backend w Node.js i osobną bazę Postgres, a potem łączyło je ze sobą. Dawniej musiałbym wdrożyć aplikację Node.js na AWS, postawić instancję Postgres na AWS i sprawić, żeby się komunikowały.
Convex: backend i baza w jednym pudełku
Ale mamy warstwę abstrakcji ponad AWS o nazwie Convex. Convex to piękna rzecz. Bierze mój serwer, czyli backend, i „poślubia” go z bazą danych — a mówiąc lepiej: dostaję jedno i drugie w jednym pudełku. Dostaję backend, w którym mogę czytać dane z bazy, zapisywać je i wchodzić w interakcję z usługami zewnętrznymi — i te operacje nie zawodzą ani nie są wolne. Dostaję też bazę danych. Zamiast zarządzać osobno backendem i osobno bazą, zarządzam jedną infrastrukturą.
Fajne w Convexie jest to, że wszystko dzieje się w czasie rzeczywistym, więc jest szybko. Jeśli znacie Convexa, to operacje nazywają się tam: queries (odczyt danych), mutations (modyfikacja danych) i actions (interakcja z usługami zewnętrznymi).
Procesy trwałe, kolejki i zadania równoległe
Jest jeszcze jedna rzecz do przemyślenia. Załóżmy, że buduję aplikację czatu. Ktoś pisze wiadomość i wychodzi z czatu — czy rozmowa będzie się toczyć dalej, czy padnie? Jeśli zbudujesz to standardowo (albo „na czuja”, nie rozumiejąc, jak działa strumień czatu), prawdopodobnie padnie. Ja wiem, że potrzebuję procesów trwałych.
Znów wielkie słowo, ale to proste: proces trwały to taki, który się nie przerywa — działa dalej, nawet jeśli zamkniesz kartę, odświeżysz stronę czy cokolwiek zrobisz. Gdybym nie miał Convexa, musiałbym to zbudować sam. Convex ma to już gotowe — nazywa się workflow. Konfiguruję to za pomocą ich komponentu workflow. A jeśli nie wiesz, jak to ustawić, wystarczy w Convexie wejść w komponenty, wyszukać „workflow” i dosłownie skopiować opis, wklejając go agentowi. Workflow upraszcza programowanie długo trwających przepływów kodu, wykonując je w sposób trwały, z konfigurowalnymi ponowieniami i opóźnieniami. Potrzebuję tego, bo buduję agenta AI, który nie może przestać pracować tylko dlatego, że ktoś wyszedł.
A gdybym chciał kolejkę? Załóżmy, że budujesz coś jak Ticketmaster i tysiące ludzi jednocześnie łomocze w twoją stronę — potrzebujesz kolejki. W klasycznej inżynierii backendu musiałbyś to zbudować sam, ale w Convexie jest to dostępne. Mogę mieć kolejki, mogę mieć skoordynowane zadania równoległe — czyli wiele rzeczy działających jednocześnie. Convex ma do tego komponent workpool.
(Informacja dodatkowa: w świecie AWS odpowiednikami byłyby SQS — Simple Queue Service dla kolejek, RDS dla bazy danych oraz EC2 dla serwerów wirtualnych. Są potężne, ale mają fatalne doświadczenie użytkownika/programisty/agenta).
Convex to upraszcza, abstrahuje i daje w jednym komplecie. Dostaję to wszystko, a na dodatek bazę danych. Zamiast budować backend i bazę osobno, po prostu używam Convexa.
Wszystko jako kod — dla agenta
Kolejny plus Convexa: wszystko jest kodem. To ważne, bo chcę, żeby robotę wykonywał agent. Chcę, żeby agent budował funkcje, żeby robił to i tamto. A jeśli cały backend to kod, jeśli baza danych to kod, jeśli wszystko jest kodem — to agent może to za mnie zrobić.
Wracając do Pluto: mamy powierzchnię kliencką, a płaszczyzną sterowania — głównym orkiestratorem, głównym backendem — jest Convex. Convex jest źródłem prawdy, mostem, obsługuje wszystko, a ja korzystam z jego komponentów.
Uwielbiam Convexa również za integracje. Załóżmy, że chcę zintegrować magazyn Cloudflare R2. Wystarczy, że wyszukam „R2” — Convex ma do tego komponent. Wiecie, jak to konfiguruję? Kopiuję link, daję go agentowi, a on wszystko ustawia. I nagle mam w aplikacji magazyn podłączony do backendu.
Serwisy: kiedy wydzielić fragment systemu
Wygląda pięknie, prawda? Mam klienta, mam backend i bazę — i to tyle. Ale zaraz, w Pluto jest znacznie więcej. Jedną z takich rzeczy są serwisy. Żeby najlepiej wyjaśnić, czym jest serwis, użyję AI: to samodzielny, wielokrotnego użytku blok funkcjonalności oprogramowania, który wykonuje określone zadanie dla innych części aplikacji lub dla klientów zewnętrznych.
W Pluto są dwa serwisy: inference/płatności oraz iMessage. Zacznę od iMessage, bo jest prostszy. Jednym ze sposobów komunikacji z agentem w Pluto — obok wewnętrznego czatu, a wkrótce także Telegrama, Slacka i Discorda — jest iMessage. Możesz rozmawiać z agentem przez iMessage. Jest z tym sporo pracy i po prostu poczułem, że kod iMessage powinien żyć we własnym, odseparowanym pudełku. Nie miesza się zbytnio z resztą kodu, nie ma zbyt wielu zaczepień w różnych miejscach i lepiej mu we własnym kącie. Ta decyzja wynikała bardziej z doświadczenia i wyczucia.
Podobnie inference/płatności. Planuję, żeby Pluto miał własny system inference, mocno spleciony z płatnościami — ludzie doładowują kredyty, a te kredyty służą do wnioskowania na różnych modelach. To wyglądało na system, który powinien stać osobno. Po pierwsze, backend w Convexie zaczął się rozrastać i chciałem oddzielić rzeczy, które mogą być samodzielnym serwisem. Po drugie, jeśli Pluto się powiedzie i będą przy nim pracować inni programiści, zakładam, że pojawi się osoba dedykowana wyłącznie temu obszarowi.
iMessage może być na to zbyt małym kawałkiem, ale to własne, odrębne pudełko i dla mnie ma sens jako osobny serwis. Kiedy myślimy o serwisach, myślmy o bloku kodu, który dotyka jednej powierzchni, robi jedną konkretną rzecz, nie ma zaczepień w całej bazie kodu, ale da się go czysto wydzielić. To bardziej doświadczenie i wyczucie niż konkretna formuła.
Stos serwisów: Effect TS i Postgres
Jakiego stosu użyłem? To może was zaskoczyć: Effect TS i Postgres. Effect TS zastosowałem w serwisie inference/płatności, a przy iMessage był to sam Effect. Dlaczego Effect? Po pierwsze, AI naprawdę dobrze pisze kod w Effekcie. Po drugie, potrzebowałem naprawdę mocnej obsługi błędów — bo jeśli w inference i płatnościach coś pójdzie nie tak, muszę o tym wiedzieć. Musi być czysto i dobrze poukładane, a w obsłudze błędów nic nie dorównuje Effektowi.
Do płatności mam osobną bazę — Postgres, hostowaną na Planet Scale, choć równie dobrze może to być dowolny inny dostawca. To również żyje w monorepo, więc niezależnie od tego, jakiego agenta używam, ma on dostęp do wszystkich informacji i rozumie, jak działa system. Projektując serwisy, zastanów się, które elementy aplikacji chcesz wydzielić — możesz też zadać to pytanie Fable 5, który wrócił do gry.
Płatności: dlaczego Autumn zamiast Stripe
Co do płatności — pewnie zastanawiacie się, czego używam. Jest Stripe, jest Polar, jest Autumn. Większość z was pewnie powie: „przecież mogłeś użyć Stripe’a”. Wybrałem Autumn, bo mam system kredytowy, a moje płatności są zaprojektowane dość nietypowo: są kredyty, są rzeczy, które kredyty zużywają, są rzeczy darmowe, są takie, które wymagają doładowania. Na przykład w Pluto możesz dać agentowi kartę — oczywiście musisz ją zasilić — i możesz doładowywać ją swoimi kredytami. Autumn dobrze to obsługuje. I znów: skoro używam Convexa, a Convex ma komponent do Autumn, po prostu skopiowałem go i dałem agentowi.
Podsumowując: jeśli to zwykła, prosta subskrypcja — użyj Stripe’a. Jeśli masz coś opartego na kredytach — użyłbym Autumn.
Logowanie błędów i analityka
Jak już widać, to spora aplikacja. Jest wiele miejsc, w których coś może pójść nie tak — w kliencie, w backendzie, w różnych serwisach, w samym monorepo. Polecam (a to nie jest współpraca sponsorowana) Sentry i PostHog. Tego używam do analityki, logowania błędów i tego typu rzeczy. Musisz mieć solidne logowanie, żeby gdy coś padnie — aplikacja się wywali albo build się nie powiedzie — dokładnie wiedzieć, co się stało. A jeśli jesteś osobą nietechniczną, po prostu powiedz AI: „Chcę mieć pewność, że za każdym razem, gdy pojawi się błąd, będę wiedział, jak go wyśledzić i kiedy się zdarzył. Użyj Sentry i PostHog, żeby to zrobić”.
Reszta układanki: inference, sandboxy i uwierzytelnianie
Na diagramie architektury (narysowanym przez agenta w Cursorze) widać płaszczyznę sterowania w Convexie i sposób użycia komponentów. Mamy system rejestru inference (inference ledger), zbudowany w Effekcie, mamy portfelowy rejestr w Postgresie, a jako bazowego dostawcę inference używamy OpenRoutera. Jako agenta wykorzystuję OpenClaw, wdrażanego na Daytonie.
Daytona jest mi potrzebna, bo to świetny dostawca sandboxów — i nie tylko dostaję sandbox, ale każdy agent dostaje też własny komputer z przeglądarką. Mój agent Pluto ma własny komputer: poprosiłem go o zrzut ekranu i choć coś się popsuło, sam się naprawił i przysłał mi zrzut. Tego nie zbudowałbym sam — potrzebuję warstwy abstrakcji, która to ułatwia, a Daytona jest w tym świetna.
Do uwierzytelniania używam WorkOS, z jednego prostego powodu: jest bardzo dobry i gotowy dla firm (enterprise-ready). W Pluto nie celuję w osoby korzystające z agenta prywatnie — chcę trafić do firm, małych i średnich, powiedzmy od 15 do 60 pracowników. Menedżer wszystko konfiguruje i zaprasza ludzi. WorkOS świetnie robi uwierzytelnianie firmowe, a jeśli potrzebuję konkretnej zgodności, bardzo to ułatwia — no i agenty go uwielbiają.
Świadome kompromisy Pluto
Kiedy patrzę na zaprojektowany system, jakie kompromisy poczyniłem? Pierwszy to koszt. Nie wiem jeszcze, jak ten biznes zarobi pieniądze. Bardziej zależy mi na tym, żeby ludzie wypróbowali Pluto i naprawdę go polubili — a zarabianie to problem na później. Dlatego nie myślałem o optymalizacji kosztów; chcę tylko mieć pewność, że kiedy ludzie użyją aplikacji, nic się nie zepsuje. Nawet boksy na Daytonie są średnie i duże, bo chcę, żeby agent każdego użytkownika był szybki. WorkOS ma dość hojny darmowy próg, Convex też. Gdybym chciał oszczędzać, wrzuciłbym po prostu wszystko do Convexa, ale trzymam osobny serwis.
Do wdrożeń używam Vercela. Mam produkcję Pluto, środowisko staging, serwis inference, panel administracyjny. Jestem na planie za 20 dolarów miesięcznie, ale wydałem już ponad 100 dolarów. Koszt to więc ten jeden obszar, gdzie mówię sobie: „trudno, dajemy czadu”.
Dlatego uważam, że budując aplikację, warto o tym myśleć — architektować ją tak, żeby dodawanie nowych funkcji i narzędzi jej nie rozwalało. Dlatego zawsze zaczynam od monorepo: jedno repozytorium, które pomieści wiele rzeczy — aplikację webową, mobilną, desktopową, jeden wspólny backend, wiele backendów, wiele serwisów. Agent ma wszystko w jednym repo, ma dostęp do całego kodu. A narzędzia, których używam, to takie, które agenty dobrze znają i umieją obsługiwać: Vercel — znakomity do wdrożeń; Convex — znakomity, bo wszystko jest kodem, więc agenty to kochają; Autumn do płatności — naprawdę dobry.
I znów: dzięki Convexowi, nawet jeśli agent nie jest świetny w obsłudze jakiegoś konkretnego narzędzia, jest świetny w używaniu komponentu Convexa. Komponent pomaga mi zintegrować ulubione narzędzia — Autumn, Stripe, cokolwiek. Po prostu wchodzę w komponenty Convexa i wyszukuję. A ponieważ tak właśnie zaczynam dziś swoje aplikacje, dodawanie serwisów i wydzielanie konkretnych rzeczy nie jest trudne — agent robi to sam.
Każde narzędzie, którego używam, radzi sobie ze skalą: Vercel, Convex, Autumn. To sprawdzone rozwiązania, z których korzysta mnóstwo ludzi i wiele odnoszących sukcesy firm. Jeśli do aplikacji dołączy tysiąc użytkowników, w większości przypadków muszę tylko podnieść plan subskrypcji, a potem mogę użyć AI do optymalizacji. Nie ma powodu, żeby aplikacja padła, bo zbudowałem ją na solidnej infrastrukturze — chyba że mam zły kod, ale tu mówimy o projektowaniu systemu.
I to w zasadzie tyle. Nie twierdzę, że to najlepszy możliwy sposób — tak po prostu myślę o aplikacjach i tak buduję je w mojej agencji Hey Fabrica. Mam nadzieję, że się przyda. Dajcie znać, czy chcecie więcej takich materiałów. Nazywam się Ross, do zobaczenia w następnym.
10 najważniejszych takeaways — z kontekstem zastosowania
1.Prototyp nie jest produktem — projekt systemu to różnica
Na czym polega: Aplikacje sklejane „na czuja” z AI padają przy kilku użytkownikach, bo brakuje im przemyślanego projektu systemu. Programista z AI zbuduje coś solidniejszego niż osoba nietechniczna właśnie dzięki wiedzy o architekturze.
Jak stosować: Zanim zaczniesz kodować z AI, rozpisz świadomie klienta, serwer i bazę danych oraz to, jak się komunikują. Traktuj AI jak wykonawcę, a nie architekta.
Na co uważać: Działający demo nie znaczy „gotowe na produkcję”. Nie myl szybkiego efektu z odpornością na realny ruch i błędy.
2.Inżynieria to kompromisy — nazwij je świadomie
Na czym polega: Nie ma systemu idealnego. Każde narzędzie i stos to kompromis między skalowalnością, niezawodnością, wydajnością i kosztem.
Jak stosować: Przy każdej decyzji technicznej jawnie zapisz, który z czterech wymiarów poświęcasz. Autor świadomie poświęcił koszt na rzecz niezawodności i szybkości.
Na co uważać: Kompromis nieświadomy staje się długiem technicznym. Jeśli świadomie odkładasz np. optymalizację kosztów, zapisz to jako decyzję i wróć do niej w wyznaczonym momencie.
3.Wykorzystuj warstwy abstrakcji zamiast walczyć z surową chmurą
Na czym polega: Dostawcy jak Convex, Vercel czy Planet Scale „owijają” AWS/GCP/Azure i zdejmują z ciebie zarządzanie infrastrukturą, oferując świetne doświadczenie zarówno dla programisty, jak i dla agenta AI.
Jak stosować: Do nowych projektów startuj od warstwy o dobrym „developer/agent experience”, a nie od surowego AWS czy Azure. Zejdź niżej dopiero, gdy naprawdę tego potrzebujesz.
Na co uważać: Abstrakcja to również zależność od dostawcy (vendor lock-in) i jego cennika. Sprawdzaj limity darmowych progów i koszt przy skali.
4.Zaczynaj od monorepo, żeby agent widział cały kod
Na czym polega: Jedno repozytorium (np. Turborepo) mieści web, mobile, desktop, backend i współdzielone biblioteki UI. Dzięki temu agent AI ma dostęp do całego kontekstu.
Jak stosować: Inicjalizuj projekt jako monorepo od pierwszego dnia, nawet jeśli na starcie masz tylko jeden klient. Współdziel komponenty i typy między powierzchniami.
Na co uważać: Rozdzielone repozytoria tworzą oddzielone konteksty, które trudno ogarnąć zarówno człowiekowi, jak i agentowi. Zadbaj o porządek, bo monorepo bez struktury też potrafi spuchnąć.
5.Klient nigdy nie rozmawia z bazą danych bezpośrednio
Na czym polega: Bezpieczny przepływ to: klient → serwer → baza → serwer → klient. Bezpośrednie połączenie klienta z bazą naraża klucze API na podejrzenie w zakładce sieciowej przeglądarki.
Jak stosować: Zawsze wstawiaj warstwę serwerową między frontend a bazę. Sekrety i klucze trzymaj wyłącznie po stronie serwera.
Na co uważać: Rozwiązania w stylu Supabase + RLS kuszą skrótem — autor uważa poleganie na samym RLS za ryzykowną „grę pozorów”. Jeśli używasz RLS, i tak nie ujawniaj wrażliwych kluczy klientowi.
6.Łącz backend i bazę w jednej infrastrukturze (Convex)
Na czym polega: Convex daje backend i bazę „w jednym pudełku”, w czasie rzeczywistym, z operacjami queries/mutations/actions — zamiast osobno zarządzanego Node.js i Postgresa.
Jak stosować: Rozważ Convex, gdy chcesz ograniczyć liczbę zarządzanych elementów i przyspieszyć pracę agenta. Korzystaj z gotowych komponentów zamiast pisać infrastrukturę od zera.
Na co uważać: Jedna infrastruktura to również jeden punkt zależności. Dla nietypowych, silnie odseparowanych obciążeń (jak inference/płatności u autora) i tak warto wydzielić osobny serwis.
7.Używaj gotowych procesów trwałych, kolejek i zadań równoległych
Na czym polega: Procesy trwałe (workflow) działają dalej mimo zamknięcia karty; kolejki i workpool obsługują nawał ruchu i zadania równoległe. Convex dostarcza je jako komponenty.
Jak stosować: Do zadań AI, strumieni czatu i długich operacji zawsze zakładaj proces trwały, nie „zwykły” request. Do skoków ruchu (typu sprzedaż biletów) planuj kolejkę.
Na co uważać: Naiwna implementacja czatu czy agenta padnie, gdy użytkownik wyjdzie albo odświeży stronę. Nie zakładaj, że użytkownik zostanie na stronie do końca operacji.
8.Wydzielaj serwis, gdy fragment jest odrębny i „samodzielny”
Na czym polega: Serwis to samodzielny blok robiący jedną rzecz, bez zaczepień w całej bazie kodu. Autor wydzielił iMessage oraz inference/płatności, dobierając do nich Effect TS ze względu na mocną obsługę błędów.
Jak stosować: Wydzielaj jako serwis to, co da się czysto odseparować, co obciąża jeden obszar i co w przyszłości może mieć dedykowanego właściciela. Dla krytycznych obszarów (płatności) wybieraj stos z solidnym error handlingiem.
Na co uważać: To decyzja „z doświadczenia i wyczucia”, nie formuła — przedwczesne dzielenie na serwisy dodaje złożoności. Wydzielaj, gdy backend faktycznie rośnie, a nie „na wszelki wypadek”.
9.Dobieraj narzędzia do modelu biznesowego, nie odwrotnie
Na czym polega: Do prostej subskrypcji wystarczy Stripe; do systemu kredytowego (doładowania, zużycie, karta dla agenta) autor wybrał Autumn. Uwierzytelnianie klasy enterprise (WorkOS) wynika z celowania w firmy.
Jak stosować: Najpierw zdefiniuj model rozliczeń i grupę docelową, potem dobierz narzędzie. Sprawdź, czy istnieje gotowy komponent integracyjny (Convex), który agent poprawnie obsłuży.
Na co uważać: „Domyślny” wybór (Stripe dla wszystkich) może nie pasować do nietypowego modelu. Agent może słabo znać samo narzędzie — łatwiej, gdy integrujesz je przez sprawdzony komponent.
10.Buduj na sprawdzonej infrastrukturze i wpinaj solidne logowanie
Na czym polega: Narzędzia radzące sobie ze skalą (Vercel, Convex, Autumn) oznaczają, że przy tysiącu użytkowników zwykle wystarczy podnieść plan. Sentry i PostHog dają wgląd w błędy i analitykę.
Jak stosować: Wybieraj „tried and true” dostawców używanych przez wiele firm, a logowanie i analitykę wpinaj od początku — nawet nietechniczny twórca może poprosić o to AI.
Na co uważać: Solidna infra nie ratuje przed złym kodem — skalowalność to nie to samo co poprawność. Bez logowania nie dowiesz się, co i kiedy się zepsuło.

