W poprzednim artykule z tej serii pokazaliśmy, jak Cloudflare Workers uruchamiają kod w setkach lokalizacji jednocześnie. Szybko jednak pojawia się pytanie: skoro izolat niczego nie pamięta między żądaniami, to gdzie trzymać dane? Najprostszą odpowiedzią Cloudflare jest Workers KV — globalnie replikowany magazyn klucz-wartość, zaprojektowany pod jedną konkretną rzecz: błyskawiczne odczyty na całym świecie. W tym artykule wyjaśniamy, jak KV działa pod maską, kiedy jest strzałem w dziesiątkę, a kiedy pułapką, i pokazujemy trzy praktyczne wzorce użycia z kodem.
Cloudflare KV — błyskawiczny magazyn danych na brzegu sieci
03.09.2026 | Autor: Marcin
Czym jest Workers KV?
KV to baza typu klucz → wartość: pod tekstowym kluczem (do 512 bajtów) przechowujesz wartość — tekst, JSON albo dane binarne do 25 MiB. Nie ma tabel, relacji ani zapytań — są cztery operacje: get, put, delete i list. Ta prostota to cena, jaką płacimy za coś wyjątkowego: dane są automatycznie replikowane do sieci Cloudflare i czytane z lokalizacji najbliższej użytkownikowi, często w czasie poniżej milisekundy dla „gorących” kluczy.
Najważniejsza rzecz: model spójności
KV jest spójny ostatecznie (eventually consistent). Zapis jest natychmiast widoczny w lokalizacji, która go przyjęła, ale do pozostałych punktów sieci propaguje się do około 60 sekund. Co z tego wynika w praktyce?
- Jeśli użytkownik z Tokio zapisze wartość, użytkownik z Warszawy może jeszcze przez chwilę widzieć starą.
- KV nie nadaje się do liczników, koszyków, blokad ani niczego, co wymaga „przeczytaj i natychmiast zaktualizuj” — dwa równoległe zapisy pod ten sam klucz kończą się tym, że wygrywa ostatni.
- Limit zapisów to 1 na sekundę na klucz — to celowy sygnał od projektantów: KV jest do czytania, nie do pisania.
Dobra heurystyka: KV pasuje tam, gdzie dane zapisujesz rzadko, a czytasz często i wszędzie. Konfiguracja, feature flagi, tokeny, cache, przekierowania, treści — tak. Stan sesji, licznik głosów, magazyn sklepu — nie (do tego służą Durable Objects albo D1, o których wspomnimy na końcu).
Konfiguracja w projekcie
Przestrzeń nazw (namespace) tworzymy Wranglerem i podpinamy do Workera jako binding:
npx wrangler kv namespace create CONFIG
Wrangler wypisze identyfikator, który dodajemy do konfiguracji projektu (wrangler.jsonc):
{
"kv_namespaces": [
{ "binding": "CONFIG", "id": "5f31...c0de" }
]
}
Od tej chwili w kodzie Workera dostępny jest obiekt env.CONFIG z metodami magazynu. Warto wiedzieć, że wartości można też zapisywać z konsoli i CI: npx wrangler kv key put --binding CONFIG "klucz" "wartość".
Wzorzec 1: cache odpowiedzi wolnego API
Najczęstszy przypadek z naszych projektów: zewnętrzne API jest wolne albo ma restrykcyjne limity, a dane zmieniają się rzadko. KV robi za globalny cache z kontrolą świeżości:
export default {
async fetch(request, env) {
const key = "exchange-rates";
const cached = await env.CONFIG.get(key, { type: "json" });
if (cached) {
return Response.json(cached);
}
const res = await fetch("https://api.nbp.pl/api/exchangerates/tables/A?format=json");
const data = await res.json();
await env.CONFIG.put(key, JSON.stringify(data), { expirationTtl: 3600 });
return Response.json(data);
}
};
Parametr expirationTtl (w sekundach) sprawia, że wpis sam zniknie po godzinie — nie musimy zarządzać unieważnianiem. Dodatkowa sztuczka: opcja cacheTtl przy odczycie pozwala jeszcze mocniej skrócić drogę dla bardzo gorących kluczy.
Wzorzec 2: feature flagi i konfiguracja bez deployu
Chcesz włączyć baner promocji w sobotę o północy albo wyłączyć eksperymentalną funkcję bez wdrożenia? Trzymaj flagi w KV:
export default {
async fetch(request, env) {
const flags = await env.CONFIG.get("feature-flags", { type: "json" }) || {};
const html = await fetch(request).then(r => r.text());
let output = html;
if (flags.promoBanner) {
output = output.replace("<!-- baner -->", '<div class="promo">Promocja weekendowa!</div>');
}
return new Response(output, { headers: { "content-type": "text/html; charset=utf-8" } });
}
};
Zmiana flagi to jeden zapis do KV — bez buildów, bez deployu, bez czyszczenia cache. W ciągu minuty nową wartość widzi cały świat. To samo podejście świetnie działa dla mapy przekierowań przy migracjach: klucz to stary adres, wartość to nowy.
Wzorzec 3: metadane i listowanie
Każdy wpis może mieć do 1024 bajtów metadanych, które są zwracane przy listowaniu — bez pobierania wartości. To przydatne np. przy panelu administracyjnym pokazującym zawartość cache:
await env.CONFIG.put("raport-2026-10", content, {
metadata: { author: "okinet", size: content.length }
});
const list = await env.CONFIG.list({ prefix: "raport-" });
// list.keys -> [{ name, expiration, metadata }, ...]
Prefiksy kluczy działają jak katalogi — warto od początku nazywać klucze hierarchicznie (cache:produkty:123), bo list filtruje wyłącznie po prefiksie.
Limity i ceny
- klucz do 512 B, wartość do 25 MiB, metadane do 1 KiB,
- 1 zapis na sekundę na pojedynczy klucz (zapisy do różnych kluczy — bez ograniczeń),
- plan darmowy: 100 tys. odczytów i 1 tys. zapisów dziennie, 1 GB danych,
- plan płatny: 10 mln odczytów w cenie, dalej ułamki dolara za milion operacji.
KV, D1 czy Durable Objects?
Cloudflare ma trzy magazyny danych i każdy służy do czego innego. KV — rzadkie zapisy, masowe globalne odczyty, spójność ostateczna. D1 — pełny SQL (SQLite), relacje i zapytania, gdy potrzebna jest struktura. Durable Objects — silna spójność i koordynacja: liczniki, kolejki, gry, wszystko, gdzie kolejność operacji ma znaczenie. Zdrowy projekt często łączy dwa z nich: konfiguracja w KV, dane transakcyjne w D1.
Podsumowanie
Workers KV to narzędzie o wąskiej, ale świetnie zrealizowanej specjalizacji: dane konfiguracyjne i cache dostępne w milisekundach na całym świecie, bez utrzymywania jakiejkolwiek infrastruktury. Trzeba tylko zapamiętać jego naturę — jest ostatecznie spójny i nie lubi częstych zapisów. W następnym artykule z serii bierzemy na warsztat Cloudflare R2, czyli obiektowy storage bez opłat za transfer — idealny między innymi na media WordPressa. A jeśli chcesz porozmawiać o edge computingu w swoim projekcie — jesteśmy pod ręką.


