Amazon DynamoDB — wyjaśnienie: budowanie skalowalnych systemów
Dowiedz się, czym jest Amazon DynamoDB, jak działa jego model NoSQL oraz praktyczne wzorce projektowe do budowy skalowalnych systemów o niskich opóźnieniach i mikrousług.

Co to jest DynamoDB i dlaczego zespoły go używają
Amazon DynamoDB to w pełni zarządzana usługa NoSQL od AWS, zaprojektowana dla aplikacji, które potrzebują stale niskich opóźnień odczytów i zapisów praktycznie przy każdej skali. „W pełni zarządzana” oznacza, że AWS zajmuje się infrastrukturą — provisioningiem sprzętu, replikacją, łatanie i wieloma zadaniami operacyjnymi — dzięki czemu zespoły mogą skupić się na dostarczaniu funkcji zamiast na utrzymaniu serwerów bazodanowych.
W istocie DynamoDB przechowuje dane jako elementy (wiersze) wewnątrz tabel, ale każdy element może mieć elastyczne atrybuty. Model danych najlepiej rozumieć jako mieszankę:
- Key-value: szybkie pobranie elementu po kluczu głównym, jak wyszukiwanie rekordu po ID.
- Document: przechowywanie zagnieżdżonych atrybutów (mapy i listy), podobnie do JSON, przydatne dla powiązanych pól bez sztywnego schematu.
Zespoły wybierają DynamoDB, gdy chcą przewidywalnej wydajności i prostszych operacji dla obciążeń, które nie pasują dobrze do relacyjnych złączeń. Często używa się go w mikrousługach (każda usługa ma swoje dane), aplikacjach serverless z nagłymi skokami ruchu oraz w systemach sterowanych zdarzeniami, które reagują na zmiany danych.
Ten artykuł przeprowadza przez podstawowe elementy (tabele, klucze i indeksy), jak modelować pod kątem wzorców dostępu (w tym projekt jednej tabeli), jak działa skalowanie i tryby pojemności oraz praktyczne wzorce dla streamowania zmian do architektury sterowanej zdarzeniami.
Podstawowe pojęcia: tabele, elementy i klucze główne
DynamoDB jest zorganizowany wokół kilku prostych bloków budulcowych, ale szczegóły mają znaczenie, bo to one decydują, jak modelujesz dane i jak szybkie (i opłacalne) będą zapytania.
Tabele, elementy i atrybuty
Tabela to najwyższy kontener. Każdy rekord w tabeli to element (podobny do wiersza), a każdy element to zestaw atrybutów (podobnych do kolumn).
W odróżnieniu od baz relacyjnych, elementy w tej samej tabeli nie muszą mieć tych samych atrybutów. Jeden element może mieć {status, total, customerId}, podczas gdy inny {status, shipmentTracking} — DynamoDB nie wymaga stałego schematu.
Klucze główne: prosty vs. złożony
Każdy element identyfikuje się unikalnie za pomocą klucza głównego, a DynamoDB obsługuje dwa typy:
- Prosty klucz główny (tylko klucz partycji): jeden atrybut identyfikuje unikalnie każdy element.
- Złożony klucz główny (klucz partycji + klucz sortujący): wiele elementów może dzielić ten sam klucz partycji, a klucz sortujący je rozróżnia i definiuje porządek w ramach tej partycji.
W praktyce klucze złożone umożliwiają „grupowane” wzorce dostępu, jak „wszystkie zamówienia klienta, od najnowszych”.
Query vs. scan (ogólnie)
Query odczytuje elementy po kluczu głównym (lub kluczu indeksu). Celuje w konkretny klucz partycji i może filtrować po zakresach klucza sortującego — to efektywna, preferowana ścieżka.
Scan przegląda całą tabelę (lub indeks) i potem filtruje. Łatwo zacząć od Scanu, ale na skali jest zwykle wolniejszy i droższy.
Ograniczenia warte zapamiętania
Kilka ograniczeń, które odczujesz wcześnie:
- Maksymalny rozmiar elementu: 400 KB.
- Typy atrybutów: skalary (string/number/binary/boolean/null), zbiory, listy i mapy.
- Atrybuty kluczy muszą być skalarnymi (nie listy/mapy jako klucze partycji lub sortujące).
Te fundamenty ustawiają wszystko, co dalej: wzorce dostępu, wybory indeksów i charakterystyki wydajności.
Model danych DynamoDB: key-value i document
DynamoDB często opisuje się zarówno jako sklep key-value, jak i bazę dokumentową. To prawda, ale warto zrozumieć, co każde z tych podejść oznacza w codziennym projektowaniu.
Dostęp key-value vs. elementy w stylu dokumentu
W swej istocie pobierasz dane po kluczu. Podajesz wartości klucza głównego, a DynamoDB zwraca pojedynczy element. To wyszukiwanie po kluczu daje przewidywalne, niskie opóźnienia dla wielu obciążeń.
Równocześnie element może zawierać zagnieżdżone atrybuty (mapy i listy), co sprawia, że przypomina bazę dokumentową: możesz przechowywać struktury bez narzucania sztywnego schematu z góry.
Modelowanie hierarchicznych struktur podobnych do JSON w elementach
Elementy naturalnie odwzorowują struktury JSON:
- Mapy reprezentują obiekty (np.
profile.name,profile.address). - Listy reprezentują tablice (np. ostatnie akcje, tagi).
To dobre dopasowanie, gdy encja jest zwykle czytana w całości — jak profil użytkownika, koszyk zakupowy czy pakiet konfiguracji.
Kiedy denormalizować (i dlaczego to powszechne)
DynamoDB nie wspiera złączeń po stronie serwera. Jeśli aplikacja musi pobrać „zamówienie plus jego pozycje plus status wysyłki” w jednej ścieżce odczytu, często denormalizuje się: kopiuje atrybuty do wielu elementów lub osadza małe podstruktury bezpośrednio w elemencie.
Kompromisy vs. relacyjnej normalizacji
Denormalizacja zwiększa złożoność zapisów i może powodować rozsyłanie aktualizacji. Korzyść to mniej rund podróży i szybsze odczyty — często kluczowe w skalowalnych systemach.
Klucz partycji i klucz sortujący: projektowanie pod wzorce dostępu
Najszybsze zapytania DynamoDB to te, które wyrazisz jako „daj mi tę partycję” (a opcjonalnie „w tej partycji daj mi ten zakres”). Dlatego wybór klucza dotyczy głównie jak czytasz dane, nie tylko jak je przechowujesz.
Klucz partycji: dystrybucja i przewidywalne odczyty
Klucz partycji decyduje, która fizyczna partycja przechowuje element. DynamoDB hashuje tę wartość, by rozłożyć dane i ruch. Jeśli wiele żądań koncentruje się na wąskim zbiorze wartości klucza partycji, możesz stworzyć „gorące” partycje i osiągnąć limity przepustowości, nawet jeśli tabela jako całość jest w większości bezczynna.
Dobre klucze partycji:
- Mają wysoką krotność wartości (dużo unikalnych wartości)
- Pasują do częstego wzorca dostępu (żeby odczyty były bezpośrednie, a nie filtrowane)
- Unikają wartości, które stają się „popularne” (np. stała
"GLOBAL")
Klucz sortujący: zapytania po zakresie i grupowanie encji
Dzięki kluczowi sortującemu elementy dzielące ten sam klucz partycji są przechowywane razem i uporządkowane według klucza sortującego. To umożliwia efektywne:
- Zapytania zakresowe (
BETWEEN,begins_with) - Odczyty w porządku czasowym (najnowsze jako pierwsze przez odwrócone skany)
- Grupowanie encji (wiele typów elementów pod jednym kluczem partycji)
Częstym wzorcem jest komponowanie klucza sortującego, np. TYPE#id lub TS#2025-12-22T10:00:00Z, by wspierać wiele kształtów zapytań bez dodatkowych tabel.
Mapowanie typowych wzorców dostępu na klucze
- Get by ID:
PK = USER#<id>(prosteGetItem) - List by user:
PK = USER#<id>,SK begins_with ORDER#(lubSK = CREATED_AT#...) - Time-series ranges:
PK = DEVICE#<id>,SK = TS#<timestamp>zBETWEENdla okien czasowych
Jak wybór klucza wpływa na wydajność i skalowalność
Jeśli klucz partycji zgadza się z Twoimi najcięższymi zapytaniami i rozkłada się równomiernie, uzyskasz stabilnie niskie opóźnienia odczytów i zapisów. Jeśli nie, będziesz rekompensować to scanami, filtrami lub dodatkowymi indeksami — każde z tych rozwiązań zwiększa koszt i ryzyko gorących kluczy.
Indeksy wtórne: wyjaśnienie GSI i LSI
Indeksy wtórne dają DynamoDB alternatywne ścieżki zapytań poza kluczem głównym tabeli. Zamiast przebudowywać tabelę, gdy pojawi się nowy wzorzec dostępu, możesz dodać indeks, który ponownie kluczuje te same elementy dla innego zapytania.
GSI vs. LSI: jaka jest różnica?
Global Secondary Index (GSI) ma własny klucz partycji (i opcjonalnie klucz sortujący), który może być całkowicie inny niż klucz tabeli. Jest „globalny”, bo obejmuje wszystkie partycje tabeli i można go dodawać lub usuwać w dowolnym momencie. Użyj GSI, gdy potrzebujesz nowego wzorca dostępu, który nie pasuje do pierwotnego projektu — np. zapytania zamówień po customerId, gdy tabela jest kluczowana po orderId.
Local Secondary Index (LSI) dzieli ten sam klucz partycji co tabela bazowa, ale używa innego klucza sortującego. LSI trzeba zdefiniować przy tworzeniu tabeli. Przydają się, gdy chcesz wielu porządków sortowania w tej samej grupie encji (ten sam klucz partycji), np. pobranie zamówień klienta posortowanych według createdAt vs. status.
Projekcje: co jest kopiowane do indeksu
Projekcja decyduje, które atrybuty DynamoDB przechowuje w indeksie:
- KEYS_ONLY: najtańsze przechowywanie, ale często trzeba wykonać dodatkowy odczyt z tabeli bazowej.
- INCLUDE: kopiuj tylko atrybuty, które najczęściej zwracasz.
- ALL: najprostsze, ale może powiększyć koszty przechowywania i zapisu.
Amplifikacja zapisu (ukryty rachunek)
Każdy zapis do tabeli bazowej może wywołać zapisy do jednego lub więcej indeksów. Więcej GSI i szersze projekcje zwiększają koszty zapisów i zużycie pojemności. Planuj indeksy wokół stabilnych wzorców dostępu i minimalizuj projekcje, gdy to możliwe.
Tryby pojemności i zachowanie skalowania
Skalowanie DynamoDB zaczyna się od wyboru: On-Demand lub Provisioned. Oba mogą osiągnąć bardzo dużą przepustowość, ale zachowują się inaczej przy zmieniającym się ruchu.
On-Demand vs. Provisioned: jak wybrać
On-Demand to najprostsze: płacisz za żądania, a DynamoDB automatycznie dopasowuje się do zmiennego obciążenia. Pasuje do nieprzewidywalnego ruchu, produktów we wczesnej fazie i obciążeń skokowych, gdy nie chcesz zarządzać celami pojemności.
Provisioned to planowanie pojemności: określasz (lub autoskalujesz) przepustowość odczytów i zapisów i uzyskujesz przewidywalniejsze koszty przy stabilnym użyciu. Często jest tańszy przy stałym ruchu i dla zespołów, które potrafią prognozować zapotrzebowanie.
Pojemność odczytu/zapisu w praktyce
Pojemność provisioned mierzona jest w:
- RCU (Read Capacity Units): mniej więcej jeden silnie spójny odczyt na sekundę dla elementu do 4 KB (lub dwa odczyty eventualnie spójne).
- WCU (Write Capacity Units): mniej więcej jeden zapis na sekundę dla elementu do 1 KB.
Rozmiar elementu i wzorzec dostępu decydują o rzeczywistych kosztach: większe elementy, silna spójność i skany szybko spalają pojemność.
Podstawy autoskalowania (i ograniczenia)
Autoskalowanie dostosowuje provisioned RCU/WCU na podstawie celów wykorzystania. Pomaga przy stopniowym wzroście i cyklicznych wzorcach, ale nie jest natychmiastowe. Nagłe skoki mogą nadal powodować throttling, jeśli pojemność nie zdąży się zwiększyć, i nie rozwiązuje problemu gorących partycji, które koncentrują ruch.
DAX: cache dla odczytów intensywnych
DynamoDB Accelerator (DAX) to cache in-memory, który może zmniejszyć opóźnienia odczytów i odciążyć powtarzane odczyty (np. popularne strony produktów, sesje, rankingi). Najlepiej sprawdza się, gdy wielu klientów wielokrotnie żąda tych samych elementów; nie pomoże przy wzorcach z dominacją zapisów i nie zastąpi starannego projektu kluczy.
Spójność, transakcje i poprawność
DynamoDB pozwala handlować gwarancjami odczytu względem opóźnień i kosztów, więc ważne jest jasne określenie, co znaczy „poprawne” dla każdej operacji.
Odczyty eventualnie spójne vs. silnie spójne
Domyślnie GetItem i Query używają eventualnej spójności: możesz chwilowo zobaczyć starszą wartość zaraz po zapisie. To często wystarcza dla feedów, katalogów produktów i innych widoków głównie do odczytu.
Przy silnie spójnych odczytach (opcja dla odczytów z tabeli bazowej w jednym regionie) DynamoDB gwarantuje, że zobaczysz najnowszy potwierdzony zapis. Silna spójność kosztuje więcej RCU i może zwiększać opóźnienia ogona, więc zarezerwuj ją dla naprawdę krytycznych odczytów.
Kiedy silna spójność ma znaczenie
Silna spójność jest ważna tam, gdzie odczyt decyduje o nieodwracalnej akcji:
- Sprawdzenie dostępności stanu magazynowego przed potwierdzeniem zamówienia
- Odczyt flagi autoryzacji przed przyznaniem dostępu
- Pobranie bieżącego stanu workflow przed wykonaniem kolejnego kroku
Dla liczników najbezpieczniej zwykle użyć aktualizacji atomowej zamiast „silny odczyt potem zapis”.
Transakcje odczytu/zapisu
Transakcje DynamoDB (TransactWriteItems, TransactGetItems) dają semantykę ACID dla do 25 elementów. Przydają się, gdy musisz zapisać wiele elementów razem — np. tworząc zamówienie i rezerwując zapas — lub gdy nie możesz dopuścić do stanów pośrednich.
Idempotencja dla bezpiecznych ponowień
Ponowienia są normalne w systemach rozproszonych. Uczyń zapisy idempotentnymi, aby ponowienia nie powodowały duplikatów:
- Użyj tokena żądania po stronie klienta (idempotency key) przechowywanego z wynikiem
- Egzekwuj unikalność za pomocą
ConditionExpression(np. "only create if attribute_not_exists") - Preferuj aktualizacje atomowe zamiast pętli odczyt-modyfikacja-zapis
Poprawność w DynamoDB polega głównie na wyborze odpowiedniego poziomu spójności i projektowaniu operacji tak, by ponowienia nie psuły danych.
Partycje, gorące klucze i skoki ruchu
DynamoDB rozkłada dane tabeli na wiele fizycznych partycji. Każda partycja ma ograniczoną przepustowość odczytów i zapisów oraz limit ilości danych, które może pomieścić. Klucz partycji decyduje, gdzie znajduje się element; jeśli zbyt wiele żądań celuje w jedną wartość klucza partycji (lub mały ich zbiór), ta partycja staje się wąskim gardłem.
Dlaczego powstają gorące partycje
Gorące partycje zwykle wynikają ze złego wyboru klucza, który koncentruje ruch: „globalny” klucz partycji jak USER#1, TENANT#default lub STATUS#OPEN, albo wzorce oparte na czasie, gdzie wszyscy zapisują do "teraz" pod jednym kluczem.
Symptomy gorących kluczy i nierównomiernego ruchu
Zazwyczaj zobaczysz:
- Throttling (
ProvisionedThroughputExceededException) dla podzbioru kluczy - Podwyższone i skokowe opóźnienia dla kilku wzorców dostępu podczas gdy inne pozostają szybkie
- Metryki CloudWatch pokazujące nierównomierne zużycie pojemności i nagłe skoki
Techniki łagodzenia
Projektuj pod dystrybucję najpierw, potem pod wygodę zapytań:
- Projekt klucza: zapewnij wysoką krotność wartości partycji (np.
TENANT#<id>zamiast stałej) - Sharding zapisu: dodaj mały losowy lub hashowany sufiks/prefiks, np.
ORDER#<id>#<shard>, by rozłożyć zapisy na N shardów, a potem zapytuj po shardach gdy trzeba - Bucketowanie czasowe: dziel według godziny/dnia (
METRIC#2025-12-22T10) by uniknąć zapisywania wszystkiego do najnowszego elementu
Obsługa skoków obciążenia
Dla nieprzewidywalnych skoków on-demand może wchłonąć natężenie (w granicach limitów usługi). Przy provisioned użyj autoskalowania i implementuj po stronie klienta exponential backoff z jitterem przy throttlingu, aby uniknąć zsynchronizowanych ponowień, które potęgują skok.
Wzorce modelowania danych dla skalowalnych systemów
Modelowanie danych w DynamoDB zaczyna się od wzorów dostępu, a nie od diagramów ER. Projektujesz klucze tak, by potrzebne zapytania stały się szybkim Query, a wszystko inne albo unikasz, albo obsługujesz asynchronicznie.
Projekt jednej tabeli (dlaczego zespoły to lubią)
„Projekt jednej tabeli” oznacza przechowywanie wielu typów encji (użytkownicy, zamówienia, wiadomości) w jednej tabeli i stosowanie spójnych konwencji kluczy, aby powiązane dane pobierać w jednym Query. Zmniejsza to liczbę rund podróży między encjami i utrzymuje przewidywalne opóźnienia.
Częste podejście to klucze złożone:
PKgrupuje logiczną partycję (np.USER#123)SKporządkuje elementy w tej grupie (np.PROFILE,ORDER#2025-12-01,MSG#000123)
To pozwala pobrać „wszystko dla użytkownika” lub „tylko zamówienia użytkownika” przez użycie prefiksu klucza sortującego.
Relacje: listy sąsiedztwa i wiele-do-wielu
Dla relacji grafowych dobrze sprawdza się lista sąsiedztwa: przechowuj krawędzie jako elementy.
PK = USER#123,SK = FOLLOWS#USER#456
By obsłużyć odwrotne wyszukiwania lub prawdziwe wiele-do-wielu, dodaj element odwrotny krawędzi lub zrób projekcję do GSI, zależnie od potrzeb odczytu.
Szereg czasowy: bucket + sort key + TTL
Dla zdarzeń i metryk unikaj nieograniczonych partycji przez bucketowanie:
PK = DEVICE#9#2025-12-22(urządzenie + dzień)SK = TS#1734825600(znacznik czasu)
Użyj TTL, by automatycznie wygaszać stare punkty, i trzymaj agregaty (godzinowe/dzienne) jako osobne elementy do szybkich dashboardów.
Jeśli chcesz głębszego przypomnienia zasad konwencji kluczy, zobacz partition-key-and-sort-key-design.
Streams i architektury sterowane zdarzeniami
DynamoDB Streams to wbudowany mechanizm CDC (change data capture). Po włączeniu dla tabeli każde wstawienie, aktualizacja lub usunięcie generuje rekord strumienia, na który konsumenci mogą reagować — bez ciągłego odpytywania tabeli.
Podstawy DynamoDB Streams
Rekord strumienia zawiera klucze i (opcjonalnie) obraz elementu przed i/lub po zmianie, zależnie od wybranego stream view type (keys only, new image, old image, both). Rekordy pogrupowane są w shardy, które czyta się sekwencyjnie.
Budowanie przepływów event-driven
Typowa konfiguracja to DynamoDB Streams → AWS Lambda, gdzie każda partia rekordów wywołuje funkcję. Można też mieć innych konsumentów (własne konsumenty lub przesyłanie do systemów analitycznych/logowania).
Typowe zastosowania:
- Materialized views: zapisz zdenormalizowany model odczytowy przy zmianie tabeli źródłowej.
- Inwalidacja cache: wygasaj lub odśwież pozycje w Redis/ElastiCache po zapisach.
- Logi audytu: dopisuj niemodyfikowalne zdarzenia zmian do tabeli audytu lub zewnętrznego magazynu.
To pozwala utrzymać tabelę główną zoptymalizowaną pod niskie opóźnienia odczytów/zapisów i przenieść pracę pochodną do konsumentów asynchronicznych.
Kolejność, ponowienia i poprawność
Streams zapewniają przetwarzanie w kolejności na shardzie (co zwykle koreluje z kluczem partycji), ale nie ma globalnej kolejności dla wszystkich kluczy. Dostawa jest co najmniej raz, więc mogą wystąpić duplikaty.
Aby to bezpiecznie obsłużyć:
- Uczyń handlery idempotentnymi (np. upsert po kluczu głównym, użyj warunkowych zapisów albo przechowuj przetworzone ID zdarzeń).
- Spodziewaj się ponowień i częściowych awarii partii; używaj DLQ/odporności na błędy, gdzie to możliwe.
- Trzymaj skutki uboczne (maile, płatności) za mechanizmami deduplikacji lub zabezpieczeniami transakcyjnymi.
Przy takim zaprojektowaniu Streams mogą uczynić z DynamoDB solidny fundament dla systemów event-driven.
Niezawodność, backupy i obserwowalność
DynamoDB jest zaprojektowany pod wysoką dostępność, rozkładając dane między wieloma Availability Zones w regionie. Dla większości zespołów praktyczne korzyści z niezawodności wynikają z jasnej strategii backupów, rozumienia opcji replikacji i monitorowania właściwych metryk.
Backupy: on-demand vs. point-in-time recovery
On-demand backups to migawki manualne (lub zautomatyzowane) robione, gdy chcesz znać punkt przywrócenia — przed migracją, po release lub przed dużym backfillem. Dobre jako „zakładki” w czasie.
Point-in-time recovery (PITR) ciągle przechwytuje zmiany, dzięki czemu możesz przywrócić tabelę do dowolnej sekundy w oknie retencji. PITR to siatka bezpieczeństwa przed przypadkowymi usunięciami, złymi deployami czy błędnymi zapisami.
Replikacja i opcje multi-region
Jeśli potrzebujesz odporności multi-region lub niskich opóźnień blisko użytkowników, Global Tables replikują dane między wybranymi regionami. Upraszczają planowanie failover, ale wprowadzają opóźnienia replikacji między regionami i kwestie rozwiązywania konfliktów — trzymaj jasne wzorce zapisu i własność elementów.
Podstawy monitoringu
Minimum, na co warto ustawić alerty:
- Opóźnienia (p95/p99) dla odczytów i zapisów
- Throttled requests i błędy systemowe
- Consumed capacity (i zapas względem provisioned)
Te sygnały zwykle sygnalizują problemy z gorącymi partycjami, niewystarczającą pojemnością lub nieoczekiwanymi wzorcami dostępu.
Playbooki incidentowe
Przy throttlingu najpierw zidentyfikuj wzorzec dostępu powodujący problem, następnie złagodź, tymczasowo przełączając na on-demand lub zwiększając provisioned capacity, i rozważ sharding gorących kluczy.
Przy częściowych awariach lub podwyższonych błędach zmniejsz zasięg: wyłącz ruch niekrytyczny, stosuj ponowienia z jitterem i degraduj działanie (np. serwuj cache), aż tabela się ustabilizuje.
Bezpieczeństwo i kontrola dostępu
Bezpieczeństwo DynamoDB to głównie doprecyzowanie kto może wywoływać które akcje API, skąd i na jakich kluczach. Ponieważ tabele mogą trzymać wiele typów encji (czasem wielu tenantów), kontrola dostępu powinna być projektowana razem z modelem danych.
Uprawnienia IAM: zasada najmniejszych przywilejów
Zacznij od polityk IAM ograniczających akcje (np. dynamodb:GetItem, Query, PutItem) do minimum i odnoszących się do konkretnych ARN tabel.
Dla drobniejszych ograniczeń użyj dynamodb:LeadingKeys, aby ograniczyć dostęp według wartości kluczy partycji — przydatne, gdy usługa lub tenant powinien mieć dostęp tylko do własnej przestrzeni kluczy.
Szyfrowanie: co sprawdzić
DynamoDB szyfruje dane w spoczynku domyślnie, używając kluczy AWS owned lub customer-managed KMS. Jeśli masz wymagania zgodności, sprawdź:
- Czy tabela korzysta z oczekiwanego klucza KMS
- Czy rola wywołująca ma potrzebne uprawnienia do KMS (i nic więcej)
Dla szyfrowania w tranzycie upewnij się, że klienci używają HTTPS (SDK AWS domyślnie tak robi). Jeśli kończysz TLS w proxy, potwierdź, że hop między proxy a DynamoDB również jest szyfrowany.
Kontrole sieciowe: ogranicz ścieżki wycieku danych
Użyj VPC Gateway Endpoint dla DynamoDB, aby ruch pozostał w sieci AWS i by móc stosować polityki endpointu ograniczające dostęp. Połącz to z kontrolami egress (NACL, security groups i routing), by unikać ścieżek „wszystko może się połączyć z internetem”.
Projekt multi-tenant i wzorce izolacji
Dla tabel współdzielonych dołącz identyfikator tenanta do klucza partycji (np. TENANT#<id>), a izolację wymuś politykami IAM na dynamodb:LeadingKeys.
Jeśli potrzebujesz silniejszej izolacji rozważ oddzielne tabele na tenantów lub środowiska; tabele współdzielone zostaw tam, gdzie prostota operacyjna i oszczędność kosztów przeważają nad mniejszym blast radiusem.
Optymalizacja kosztów dla DynamoDB
DynamoDB jest często „tani, gdy jesteś precyzyjny, drogi, gdy jesteś nieostrożny”. Koszty zwykle podążają za wzorcami dostępu, więc najlepsza optymalizacja zaczyna się od jawnego określenia tych wzorców.
Zrozum czynniki kosztotwórcze
Twoje rachunki kształtują się głównie przez:
- Odczyty i zapisy (RCU/WCU w trybie provisioned, żądania w on-demand)
- Przechowywanie (dane tabeli i rozmiar elementu)
- Indeksy wtórne (każdy GSI ma własne koszty zapisu i przechowywania)
- Streams (odczyty rekordów strumienia i downstream konsumenci)
Częste zaskoczenie: każdy zapis do tabeli jest też zapisem do każdego wpływającego GSI, więc „jeszcze jeden indeks” może pomnożyć koszty zapisów.
Projektuj klucze, by unikać marnotrawstwa
Dobry projekt kluczy redukuje potrzebę kosztownych operacji. Jeśli często używasz Scan, płacisz za czytanie danych, które zaraz odrzucasz.
Preferuj:
Querypo kluczu partycji (i opcjonalnie warunkach klucza sortującego)- Wąskie projekcje w GSI (kopiuj tylko to, co naprawdę potrzebne)
Jeśli wzorzec dostępu jest rzadki, rozważ obsłużenie go przez oddzielną tabelę, zadanie ETL lub zbuforowany model odczytowy zamiast stałego GSI.
Kontroluj przechowywanie przez TTL i lifecycle
Użyj TTL, by automatycznie usuwać krótkotrwałe elementy (sesje, tymczasowe tokeny, stan pośredni workflow). To zmniejsza koszty przechowywania i może utrzymać indeksy mniejsze w czasie.
Dla danych append-only (zdarzenia, logi) łącz TTL z projektem klucza sortującego, który pozwala zapytywać „tylko niedawne”, by nie dotykać zimnej historii.
Dobierz pojemność i unikaj przypadkowych skoków
W trybie provisioned ustaw konserwatywne baseline’y i skaluj z autoskalowaniem opartym na rzeczywistych metrykach. W on-demand obserwuj nieefektywne wzorce (duże elementy, głośni klienci), które generują wolumen żądań.
Traktuj Scan jako ostateczność — gdy naprawdę potrzebujesz pełnego przetworzenia tabeli, wykonuj to poza godzinami szczytu lub jako kontrolowany batch z paginacją i backoffem.
Kiedy wybrać DynamoDB (a kiedy nie)
DynamoDB błyszczy, gdy aplikację można wyrazić jako zestaw zdefiniowanych wzorców dostępu i potrzebujesz stale niskich opóźnień przy dużej skali. Jeśli potrafisz opisać swoje odczyty i zapisy z wyprzedzeniem (po kluczu partycji, kluczu sortującym i kilku indeksach), często jest to jedno z najprostszych rozwiązań do utrzymania wysoce dostępnego magazynu danych.
Dobre dopasowania
DynamoDB to dobry wybór gdy masz:
- Znane zapytania (pobierz profil użytkownika, lista zamówień użytkownika według czasu, sesja po ID)
- Dużą przepustowość zapisów lub skokowy ruch, którego nie chcesz ręcznie obsługiwać
- Potrzebę skalowania horyzontalnego bez zarządzania serwerami
- Projekty event-driven wykorzystujące Streams do uruchamiania pracy downstream
Kiedy rozważyć alternatywy
Szukaj innego rozwiązania, jeśli Twoje kluczowe potrzeby obejmują:
- Złożone złączenia między wieloma encjami lub częste traversale relacji
- Ad hoc zapytania i analizy zmieniające się co tydzień (group-by, eksploracyjne filtry)
- Intensywne wyszukiwanie tekstowe i ranking bez zewnętrznego indeksu
Podejścia hybrydowe, które działają
Wiele zespołów trzyma DynamoDB do „gorących” operacyjnych odczytów i zapisów, a do tego dodaje:
- S3 + Athena do analiz i raportów historycznych
- OpenSearch (lub podobne) do wyszukiwania pełnotekstowego i facetingu
- Warstwę cache, gdy pewne klucze są ekstremalnie odczytywane
Uwaga przy prototypowaniu: skróć drogę od modelu do aplikacji
Jeśli walidujesz wzorce dostępu i konwencje jednej tabeli, szybkość ma znaczenie. Zespoły czasem prototypują serwis i UI w Koder.ai (platforma vibe-coding, która buduje aplikacje webowe, serwisy i mobilne z konwersacji) i potem iterują nad projektem kluczy DynamoDB w miarę pojawiania się rzeczywistych ścieżek zapytań. Nawet jeśli produkcyjne zaplecze będzie inne, szybkie prototypy ujawniają, które zapytania powinny być Query, a które przypadkowo stałyby się kosztownymi scanami.
Szybka checklista decyzyjna
Zwaliduj: (1) twoje główne zapytania są znane i oparte na kluczach, (2) wymagania poprawności pasują do modelu spójności, (3) rozmiary elementów i prognozy wzrostu są zrozumiane, oraz (4) model kosztów (on-demand vs provisioned + autoscaling) pasuje do budżetu.
Często zadawane pytania
Czym jest DynamoDB i kiedy warto jej użyć?
DynamoDB to w pełni zarządzana baza NoSQL w AWS zaprojektowana do stale niskich opóźnień odczytów i zapisów przy bardzo dużej skali. Zespół wybiera ją, gdy potrafi zdefiniować dostęp wg kluczy (pobierz po ID, lista należąca do właściciela, zapytania po przedziale czasowym) i chce uniknąć operowania infrastrukturą bazodanową.
Jest szczególnie popularna w mikrousługach, aplikacjach serverless oraz systemach sterowanych zdarzeniami.
Czym są tabele, elementy i atrybuty w DynamoDB?
Tabela przechowuje elementy (jak wiersze). Każdy element to elastyczny zestaw atrybutów (jak kolumny) i może zawierać zagnieżdżone dane.
DynamoDB sprawdza się, gdy jedno zapytanie zwykle potrzebuje „całej encji”, ponieważ elementy mogą mieć mapy i listy (struktury przypominające JSON).
Jaka jest różnica między prostym kluczem głównym a złożonym kluczem głównym?
Samodzielnie identyfikuje element tylko klucz partycji (prosty klucz główny). Klucz złożony (klucz partycji + klucz sortujący) pozwala, by wiele elementów miało ten sam klucz partycji, a klucz sortujący je rozróżniał i porządkował.
Klucze złożone umożliwiają wzorce takie jak:
- „Wszystkie zamówienia klienta”
- „Zdarzenia urządzenia między znacznikami czasu”
Kiedy powinienem używać Query, a kiedy Scan?
Używaj Query, gdy możesz podać klucz partycji (i opcjonalnie warunek na klucz sortujący). To szybka i skalowalna ścieżka.
Używaj Scan tylko jeśli naprawdę musisz odczytać wszystko; skanuje całą tabelę lub indeks, a potem filtruje, co zwykle jest wolniejsze i droższe.
Jeśli często skanujesz, to znak, że projekt kluczy lub indeksów wymaga poprawy.
Czym są GSI i LSI i jak wybrać?
Indeksy wtórne dają alternatywne ścieżki zapytań.
- GSI (Global Secondary Index): może mieć inny klucz partycji (i opcjonalnie sortujący) niż tabela podstawowa; można go dodawać później.
- LSI (Local Secondary Index): dzieli ten sam klucz partycji co tabela bazowa, ale ma inny klucz sortujący; trzeba go zdefiniować przy tworzeniu tabeli.
Indeksy zwiększają koszt zapisu, bo zapisy są replikowane do indeksów.
Jak wybrać między On-Demand a Provisioned?
Wybierz On-Demand, gdy ruch jest nieprzewidywalny, skokowy lub nie chcesz zarządzać pojemnością. Płacisz za żądanie.
Wybierz Provisioned, gdy użycie jest stałe/przewidywalne i chcesz niższych kosztów przy stabilnym obciążeniu. Połącz to z autoskalowaniem, pamiętając, że nie reaguje ono natychmiast na nagłe skoki.
Jakie opcje spójności oferuje DynamoDB i kiedy mają znaczenie?
Domyślnie odczyty są eventualnie spójne, więc tuż po zapisie możesz chwilowo odczytać starszą wartość.
Użyj silnie spójnych odczytów (gdy są dostępne), gdy musisz mieć gwarancję najświeższych danych — np. przy weryfikacji autoryzacji czy krytycznych kontrolkach.
Dla poprawności przy konkurencji preferuj operacje atomowe (np. UpdateItem z ADD) zamiast pętli odczyt-modyfikacja-zapis.
Kiedy powinienem używać transakcji DynamoDB?
Transakcje (TransactWriteItems, TransactGetItems) zapewniają ACID dla maksymalnie 25 elementów.
Użyj ich, gdy musisz zaktualizować wiele elementów razem (np. stworzyć zamówienie i zarezerwować stan magazynowy) lub wymusić inwarianty, które nie tolerują stanów pośrednich.
Są droższe i podnoszą opóźnienia, więc stosuj je tam, gdzie są naprawdę potrzebne.
Czym są hot keys/partitions i jak ich unikać?
Gorące partycje występują, gdy zbyt wiele żądań trafia w ten sam wartość klucza partycji (lub malą grupę wartości), powodując throttling mimo, że tabela jako całość jest mało obciążona.
Typowe sposoby łagodzenia:
- Wybierz klucze o wysokiej krotności wartości
- Dodaj sharding zapisu (mały losowy/hashowany sufiks)
- Użyj bucketów czasowych dla danych czasowych
- Implementuj exponential backoff z jitterem przy throttlingu
Jak DynamoDB Streams wspierają architektury event-driven?
Włącz DynamoDB Streams, aby mieć strumień zmian przy insertach, update'ach i delete'ach. Typowy wzorzec to Streams → Lambda do uruchamiania pracy downstream.
Gwarancje, o których trzeba pamiętać:
- Kolejność jest zachowana na poziomie sharda (nie globalnie)
- Dostawa jest co najmniej raz (mogą wystąpić duplikaty)
Spraw, by konsumenci byli idempotentni (upsert po kluczu, warunkowe zapisy lub śledzenie ID przetworzonych zdarzeń).