W zeszły weekend potrzebowałem publicznego endpointu do odbierania zgłoszeń z formularza na landing page'u. Nic wymyślnego — przyjąć POST z JSON-em, zwalidować kilka pól, zwrócić sensowną odpowiedź. Całość obsłużyłaby może 50 requestów tygodniowo. Nie chciałem wbijać karty kredytowej do serwera za 20 dolarów miesięcznie, uczyć się nowego narzędzia infra ani siedzieć przy pipelinie CI za każdym razem, kiedy zmieniam trzy linijki. Dziesięć minut po tym jak zacząłem, API było żywe w 300+ miastach i nie kosztowało mnie ani grosza. Oto cały spacer.
Cloudflare Workers
ma darmowy tier, który jest naprawdę hojny: 100 000 requestów dziennie, brak karty kredytowej przy
rejestracji, a twój kod biegnie na krawędzi zamiast w jednym regionie. Dla małych API, których potrzebuje większość
side-projectów — odbiorników webhooków, handlerów formularzy, skracaczy linków, proxy JSON — możesz
wypuścić i zapomnieć. Ten przewodnik prowadzi cię od "brak konta na Cloudflare" do "żywy URL odpowiada
na curl" w jakieś dziesięć minut. Zbudujemy prawdziwy endpoint: walidator JSON-a,
który przyjmuje POST, sprawdza payload i odsyła czystą odpowiedź.
Co dostajesz za darmo (a czego nie)
Plan free Cloudflare Workers daje ci 100 000 requestów dziennie i 10 milisekund czasu CPU na request. Brzmi ciasno, dopóki nie zdasz sobie sprawy, że większość endpointów JSON — sparsuj body, zrób odrobinę pracy, zwróć odpowiedź — kończy się grubo poniżej 1 ms. Sufit 10 ms to czas CPU, nie czas zegarowy, więc upstreamowy fetch trwający 800 ms wciąż liczy się jako mniej więcej 1 ms CPU, bo twój kod głównie czeka na I/O.
Czego nie dostajesz na planie free: pamięci trwałej o wysokim throughput (Workers KV ma własną darmową kwotę — hojną w większości przypadków, ale oddzielną od liczby requestów), dużych payloadów odpowiedzi ani triggerów cron częściej niż raz na minutę. Dla typowego serwisu "odbierz JSON, zrób coś, zwróć JSON", który nie potrzebuje bazy danych, nie uderzysz w ścianę.
Zainstaluj Node.js i Wranglera
Wrangler to CLI Cloudflare'a do Workers. Zainstaluj go przez npm — będziesz potrzebował Node.js 18 lub nowszego. Jeśli już masz Node'a, to one-liner:
npm install -g wrangler
# Verify
wrangler --version
# Should print 3.x or higherTeraz się zaloguj. To otworzy przeglądarkę po OAuth, założy konto Cloudflare jeśli go jeszcze nie masz, i lokalnie zapisze poświadczenia:
wrangler login
# Opens https://dash.cloudflare.com/oauth/authorize ...
# After you approve: "Successfully logged in."Zescaffolduj projekt
Jedna komenda i masz szkielet projektu z sensownymi domyślnymi ustawieniami — przykładowy
handler fetch, plik konfiguracyjny wrangler.toml i lokalny serwer dev gotowy
do pracy:
npm create cloudflare@latest free-json-api
# When prompted, pick:
# "Hello World" Worker
# JavaScript (or TypeScript — your call)
# No deploy yet (we'll do that ourselves)
cd free-json-apiGenerator wrzuca wszystko, czego potrzebujesz, do jednego folderu. Otwórz src/index.js —
to plik, który uruchamia twojego Workera. Zastąpimy jego zawartość czymś bardziej użytecznym
niż domyślne Hello World.
Napisz API JSON
Oto kompletny Worker, który przyjmuje POST z JSON-em, waliduje dwa wymagane pola i zwraca czystą odpowiedź. Obsługuje typowe ścieżki błędów — zła metoda, niepoprawny JSON, brakujące pola — zamiast wybuchać do generycznego 500:
export default {
async fetch(request) {
if (request.method !== 'POST') {
return Response.json(
{ error: 'POST only' },
{ status: 405 },
);
}
let body;
try {
body = await request.json();
} catch {
return Response.json(
{ error: 'Body must be valid JSON' },
{ status: 400 },
);
}
const { email, message } = body;
if (typeof email !== 'string' || typeof message !== 'string') {
return Response.json(
{ error: 'email and message are required (strings)' },
{ status: 422 },
);
}
return Response.json({
ok: true,
receivedAt: new Date().toISOString(),
echo: { email, message },
});
},
};Dwie rzeczy warte podkreślenia.
Response.json()
serializuje obiekt i ustawia za ciebie Content-Type: application/json, więc nie musisz
pamiętać o nagłówku. A zawijanie request.json() w try/catch to najważniejszy nawyk
przy budowaniu Workerów — bez tego niepoprawny payload zwraca nieprzejrzysty 500 z runtime'u Cloudflare'a
zamiast użytecznego 400 z twojego kodu.
Przetestuj lokalnie
Wrangler ma wbudowany lokalny serwer dev, który uruchamia ten sam izolat V8, którego Cloudflare używa na produkcji. Odpal go:
npm run dev
# ⛅️ wrangler 3.x
# [wrangler:inf] Ready on http://localhost:8787W innym terminalu uderz w niego curl-em. Spróbuj najpierw happy path, potem
celowo zepsutego payloadu — powinieneś zobaczyć czyste błędy JSON zamiast stack trace'ów:
# Happy path
curl -X POST http://localhost:8787 \
-H "Content-Type: application/json" \
-d '{"email":"[email protected]","message":"hello"}'
# {"ok":true,"receivedAt":"2025-10-15T...","echo":{...}}
# Broken JSON (note the missing closing brace)
curl -X POST http://localhost:8787 \
-H "Content-Type: application/json" \
-d '{"email": "ava"'
# {"error":"Body must be valid JSON"}
# Missing required field
curl -X POST http://localhost:8787 \
-H "Content-Type: application/json" \
-d '{"email":"[email protected]"}'
# {"error":"email and message are required (strings)"}Zdeployuj na świat — jedną komendą
Kiedy lokalnie działa, wypchnij to globalnie:
npx wrangler deploy
# Total Upload: 1.18 KiB / gzip: 0.55 KiB
# Uploaded free-json-api (1.34 sec)
# Published free-json-api (4.21 sec)
# https://free-json-api.<your-subdomain>.workers.dev
# Current Deployment ID: ...Ten URL jest teraz żywy w każdym data center Cloudflare'a. Request z Berlina trafia
do Frankfurtu, jeden z Tokio do Tokio, jeden z São Paulo do São Paulo — ten sam kod, zero dodatkowej
konfiguracji. Bundle ważył 1,2 KiB. Przetestuj żywy URL tymi samymi komendami curl,
których używałeś lokalnie — po prostu zamień localhost:8787 na hostname
workers.dev, który Wrangler wypisał.
Kiedy wyrośniesz z darmowego tieru
Przez długi czas nie wyrośniesz. 100 tys. requestów dziennie to mniej więcej 1,15 requesta na sekundę uśrednione przez 24 godziny — komfortowo więcej niż większość side-projectów, narzędzi wewnętrznych czy wczesnoetapowych produktów. Pierwsze, co zwykle wypycha cię z darmowego tieru, to nie liczba requestów, tylko storage: jeśli zaczniesz dużo pisać do KV, R2 albo D1, mają one swoje własne kwoty. Plan płatny zaczyna się od 5 dolarów miesięcznie i daje ci 10 milionów requestów, więcej CPU na request i siatkę bezpieczeństwa kartą kredytową na skoki ruchu. Większość projektów nigdy go nie potrzebuje.
Co dalej
To, co właśnie wypuściłeś, to absolutne minimum użytecznego Workera. Prawdziwe produkcyjne endpointy potrzebują kilku dodatkowych nawyków — CORS dla wywołań z przeglądarki, zarządzanie sekretami dla kluczy API, cachowanie na krawędzi dla wolnych upstreamów i strategia proxy do serwisów upstream. Pokrywam te tematy w Cloudflare Workers i JSON — praktyczny przewodnik, który podchwytuje tam, gdzie kończy się ten artykuł.
Kilka narzędzi, które trzymam otwarte, gdy buduję Workery operujące na JSON-ie: JSON Formatter do pretty-printowania odpowiedzi, JSON Validator, kiedy trzeba dokładnie ustalić, dlaczego payload został odrzucony, oraz JSON Path do planowania logiki wybierania pól, zanim ją napiszę. Sam format JSON jest wyspecyfikowany w RFC 8259 — warto go przejrzeć, kiedy zaczniesz obsługiwać dziwne dane od prawdziwych użytkowników.
Po głębsze wzorce dla Workerów — KV storage, Durable Objects, scheduled triggers, bindingi do AI inference — najlepszym źródłem, jakie znalazłem, jest galeria przykładów Workers Cloudflare'a. To gotowa do skopiowania lista przepisów na kolejne kroki.
Podsumowanie
Cloudflare Workers to rzadki darmowy tier, który jest faktycznie sensowny dla prawdziwych side-projectów. Brak karty kredytowej na start, 100 tys. requestów dziennie i deploy mieszczący się w jednej komendzie. Wzorzec z tego artykułu — przyjmij JSON, zwaliduj, zwróć JSON — pokrywa zaskakująco dużo z tego, co robi większość API. Jeśli wstrzymujesz się z wypuszczeniem małego API, bo infra wydaje się harówą, to jest ścieżka, którą sam chciałbym był wybrać trzy lata temu.