Cloud Intelligence™
DynamoDB: Was die meisten Teams falsch machen, bevor sie die erste Zeile Code schreiben
Diese Seite ist auch in English, Español, Français, Italiano, 日本語 und Português verfügbar.
About Joseph Allam
Databases have been my craft for a long time — long before the cloud, and deep into it across AWS and GCP. I know what breaks, what costs too much, and what needs rethinking before it hurts. I also know how to bring AI into the work: into how databases are designed, operated, and accessed by the intelligent systems being built on top of them.
My personal pageAm Prime Day 2025 erreichte Amazon DynamoDB in der Spitze 151 Millionen Anfragen pro Sekunde. Sie ist die Datenbank hinter einigen der anspruchsvollsten Workloads der Welt – und das seit fast zwei Jahrzehnten. Die meisten Engineers, die mit AWS arbeiten, haben davon gehört. Viele haben sie genutzt. Doch beim DynamoDB Immersion Day, den ich kürzlich gemeinsam mit dem AWS-Team durchgeführt habe, tauchte in fast jeder Session dasselbe Problem auf: Teams, die sich aus den richtigen Gründen für DynamoDB entschieden hatten, hatten trotzdem Schwierigkeiten – weil sie ihre Schemas falsch entwarfen.
Genau darum geht es in diesem Beitrag. Nicht um DynamoDB-Grundlagen (davon gibt es anderswo genug), sondern um das Design-Denken, das die Teams mit gut funktionierenden Setups von jenen unterscheidet, die am Ende mit ausufernden Kosten und nicht skalierenden Tabellen dastehen.
PerfectScale™ for Kubernetes
Ready to optimize?
Get your free Kubernetes savings analysis

Ist DynamoDB die richtige Wahl?
Bevor es ums Design geht, lohnt sich ein ehrlicher Blick auf die Eignung. DynamoDB ist eine gute Wahl, wenn Sie konsistente Latenz im einstelligen Millisekundenbereich bei praktisch beliebiger Skalierung benötigen, Ihre Zugriffsmuster von Anfang an bekannt und vorhersehbar sind und Ihr Workload lese-/schreibintensiv statt analytisch komplex ist. Gute Beispiele: nutzerseitige APIs, Session-Stores, Leaderboards, Warenkörbe, IoT-Ingestion, Event Sourcing.
Eine schlechte Wahl ist sie, wenn Sie Ad-hoc-Abfragen über viele Dimensionen benötigen, Ihre Zugriffsmuster sich noch weiterentwickeln oder Sie mit komplexen relationalen Joins arbeiten. Wenn Sie eine Reporting-Datenbank ersetzen oder etwas bauen, dessen Abfrageanforderungen sich von Monat zu Monat ändern, werden Sie permanent gegen DynamoDB ankämpfen.
Die Item-Größe fällt stärker ins Gewicht, als die meisten Teams erwarten
Bevor Sie sich auf DynamoDB festlegen, sollten Sie die Kosten sauber modellieren. DynamoDB berechnet Schreibkapazität in 1-KB-Schritten, aufgerundet. Im On-Demand-Modus verbraucht ein 20-KB-Item 20 Write Request Units (WRUs); im Provisioned-Modus verbraucht derselbe Schreibvorgang 20 Write Capacity Units (WCUs). Lesevorgänge funktionieren ähnlich und werden in 4-KB-Schritten pro Read Capacity Unit (RCU) abgerechnet – die Item-Größe treibt also beide Seiten Ihrer Kapazitätskosten.
Das klingt simpel, doch die Item-Größe ist eine der am häufigsten übersehenen Variablen, wenn Teams DynamoDB-Kosten modellieren. Wir sehen regelmäßig Kunden, die von relationalen Datenbanken wie PostgreSQL migrieren, wo es das Konzept einer byteweisen Abrechnung von Schreibvorgängen nicht gibt – und deren erste Kostenschätzungen deutlich danebenliegen, weil die Item-Größe nicht korrekt berücksichtigt wurde. Diese Zahl vor der Entscheidung richtig zu ermitteln, verändert die Wirtschaftlichkeit grundlegend.
Es geht nicht darum, dass DynamoDB teuer ist. Entscheidend ist, dass sich das Kostenmodell von dem unterscheidet, was die meisten Engineers gewohnt sind – und dass die Variablen dahinter (Item-Größe, Effizienz der Zugriffsmuster, On-Demand vs. Provisioned Capacity) verstanden sein müssen, bevor Sie sich festlegen, nicht danach.
Der Perspektivwechsel, der alles verändert
Die meisten Engineers bringen aus der relationalen Welt Folgendes zu DynamoDB mit: Sie entwerfen zuerst das Schema und kümmern sich danach um die Abfragen.
Bei einer relationalen Datenbank funktioniert das meist. Daten normalisieren, Indizes später aufbauen, Abfragen schreiben, die über Tabellen hinweg joinen. Die Datenbank-Engine übernimmt einen Großteil der Abfragekomplexität.
DynamoDB funktioniert anders. Im Gegensatz zu relationalen Datenbanken optimiert sie beliebige Abfragen nicht über einen Query Planner. Stattdessen leitet sie jede Anfrage über den Hash des Partition Keys direkt an die Partition weiter, auf der die Daten liegen – einer der Gründe, warum DynamoDB unabhängig von der Tabellengröße konstant Latenzen im einstelligen Millisekundenbereich liefern kann. Der Kompromiss: Die Datenbank ist auf genau eine Sache optimiert – Items effizient über schlüsselbasierte Zugriffsmuster abzurufen, über den Primary Key oder Sekundärindizes. Alles andere (Filtern, Sortieren nach Nicht-Schlüssel-Attributen, Abfragen über Entitätsbeziehungen hinweg) ist entweder teuer oder erfordert zusätzliche, im Voraus entworfene Indizes.
Der entscheidende Unterschied: Sie müssen Ihre Zugriffsmuster kennen, bevor Sie Ihre Tabelle entwerfen. Nicht ungefähr. Konkret. "Alle Bestellungen eines Nutzers, sortiert nach Datum" ist ein Design-Input. "Die 10 neuesten eskalierten Support-Tickets für einen bestimmten Account" ist ein Design-Input. Ihr Schema leitet sich aus diesen Fragen ab, nicht aus der Struktur der Daten.
In der Praxis bedeutet das: Eine einzige DynamoDB-Tabelle speichert oft mehrere Entitätstypen nebeneinander, mit Partition Keys und Sort Keys, die so konstruiert sind, dass sie konkrete Fragen effizient beantworten. Für alle, die aus der normalisierten SQL-Welt kommen, sieht das falsch aus. Ist es aber nicht. Genau darum geht es.
Zusammengesetzte Sort Keys
Nehmen wir ein gängiges Beispiel: die Bestellungen eines Nutzers, die nach Status und Datum abgefragt werden sollen. Der naive Ansatz speichert Status und Datum als separate Attribute und filtert dann beim Lesen. Das Ergebnis: Sie lesen jede Bestellung dieses Nutzers und verwerfen alle, die nicht passen.
Der Access-Pattern-First-Ansatz kodiert die Abfrage direkt in den Sort Key:
| PK | SK |
|---|---|
| user#123 | ACTIVE#2024-07-15 |
| user#123 | ACTIVE#2024-07-01 |
| user#123 | COMPLETED#2024-06-20 |
| user#123 | COMPLETED#2024-06-10 |
Jetzt liefert eine einzige Abfrage mit BEGINS_WITH("ACTIVE#") nur die aktiven Bestellungen, sortiert nach Datum – ohne eine einzige abgeschlossene Bestellung zu lesen. Sie zahlen exakt für das, was Sie abrufen.
Das funktioniert, weil BEGINS_WITH eine Präfix-Abfrage auf dem Sort Key ist. Die gröbste Gruppierung muss vorn stehen, damit DynamoDB sie zum Eingrenzen des Bereichs nutzen kann. Ein gängiger Ansatz: die breiteste Bedingung links platzieren und zunehmend spezifischere Komponenten nach rechts, sodass Präfix-Abfragen die relevante Teilmenge gezielt und effizient treffen.
Sparse Global Secondary Indexes
Ein weiteres Muster, das sich aus dem Access-Pattern-First-Denken ergibt: Wenn nur ein kleiner Teil Ihrer Items jemals eine Bedingung erfüllt (eskalierte Tickets, markierte Datensätze, Items in Prüfung), modellieren Sie diese Bedingung als Attribut, das nur auf diesen Items existiert. Ein GSI auf diesem Attribut indexiert nur die Items, bei denen es vorhanden ist.
Das entscheidende Verhalten dabei: DynamoDB nimmt ein Item nicht in einen GSI auf, wenn das indexierte Attribut fehlt (nicht nur null, sondern komplett nicht im Item vorhanden). Sie können einen GSI also ganz bewusst sparse gestalten, indem Sie das Attribut bei Items weglassen, die nicht indexiert werden sollen.
Wenn 2 % Ihrer Tickets eskaliert sind, enthält der GSI 2 % der Tabelle. Ihn abzufragen ist erheblich günstiger, als die gesamte Tabelle zu scannen und zu filtern. Der GSI ist bewusst sparse – nicht aus Versehen.
Your cloud bill shouldn't be a mystery
Optimization, automation, expertise. In one platform.
Die Fehler, die auf Ihrer Rechnung landen
Diese Fehler verdienen es, konkret benannt zu werden: Sie sind häufig, sie bleiben unsichtbar, bis Sie in Ihre Kostenberichte schauen, und sie stammen meist von Engineers, die DynamoDB eigentlich recht gut verstehen.
Filter Expressions
DynamoDB unterstützt durchaus das Filtern von Abfrageergebnissen nach dem Abruf. Das Problem: Eine FilterExpression reduziert nicht die verbrauchten Kapazitätseinheiten – sie reduziert nur, was an den Aufrufer zurückgegeben wird. Liest eine Abfrage 500 Items, bevor der Filter greift, zahlen Sie für alle bis dahin gelesenen Daten – unabhängig davon, wie viele Items der Aufrufer am Ende erhält.
Das wird schnell teuer, wenn es die primäre Strategie zum Eingrenzen von Ergebnissen ist. Es fühlt sich an wie eine SQL-WHERE-Klausel und wird deshalb gern eingesetzt, ohne über die Kosten nachzudenken. Die Lösung besteht fast immer darin, die Schlüsselstruktur so umzugestalten, dass die Datenbank nur das abruft, was Sie tatsächlich brauchen. Filter Expressions haben ihre Berechtigung, aber sie sollten in Ihrer Abfragestrategie keine tragende Rolle spielen.
Hot Partitions durch zeitbasierte Schlüssel
Ein gängiges Muster bei Zeitreihendaten: der aktuelle Zeitstempel oder die aktuelle Stunde als Partition Key. Die Logik wirkt intuitiv: Partitionierung nach Zeitfenster. Das Problem: Alle Schreibvorgänge zielen auf denselben logischen Partition Key, wodurch DynamoDB den Schreib-Traffic nicht gleichmäßig über die Partitionen verteilen kann. Bei jedem nennenswerten Schreibvolumen führt das zu Throttling.
DynamoDB verfügt zwar über Adaptive Capacity, die den Durchsatz automatisch in Richtung stärker frequentierter Partitionen umverteilt. Bei moderat verzerrter Lastverteilung löst sie das Problem oft unbemerkt. Doch keine noch so gute Adaptive Capacity kompensiert einen einzelnen Partition Key, der dauerhaft extremen Traffic erhält – und ein Zeitfenster-Schlüssel unter hoher Schreiblast ist genau diese Situation.
Die Lösung ist Write Sharding: Hängen Sie ein zufälliges Suffix an den Partition Key an (zum Beispiel EVENTS#4, wobei das Suffix eine Zahl zwischen 0 und N ist), um Schreibvorgänge auf mehrere logische Partitionen zu verteilen. Beim Lesen fragen Sie jeden Shard parallel ab und führen die Ergebnisse zusammen. Das erfordert mehr Anwendungscode, verhindert aber, dass ein schreibintensiver Workload an einer einzelnen Partition zum Flaschenhals wird.
Table Scans
Der dritte Punkt, der genannt werden muss: vollständige Table Scans. DynamoDB unterstützt Scan-Operationen, und Engineers greifen manchmal darauf zurück, wenn die GSIs ausgeschöpft sind oder nach einem nicht indexierten Attribut abgefragt werden muss. Das Problem: Ein Scan liest jedes Item der Tabelle – unabhängig davon, wie viele Treffer es gibt. Bei einer großen Tabelle ist das langsam und teuer zugleich.
Für Migrationen, Exporte, Admin-Jobs oder Hintergrundverarbeitung, bei der Latenz keine Rolle spielt, sind Scans völlig in Ordnung. Problematisch wird es, wenn sie in nutzerseitigen Request-Pfaden landen. Steckt ein Scan im kritischen Ablauf Ihrer Anwendung, ist das fast immer ein Signal, dass die Zugriffsmuster im Schemadesign nicht vollständig berücksichtigt wurden. Die Lösung ist meist ein neuer GSI oder ein neu gestalteter Sort Key – nicht ein schnellerer Scan.
Fazit
DynamoDB ist wirklich leistungsstark und für die richtigen Workloads eine der besten Datenbanken, die AWS zu bieten hat. Aber die Lücke zwischen "die richtige Datenbank gewählt" und "sie richtig designt" ist groß – und sie zeigt sich auf Ihrer AWS-Rechnung, bevor sie irgendwo anders sichtbar wird. Das Kostenmodell ist anders, der Designprozess ist anders, und die Fehler unterscheiden sich von dem, was die meisten Engineers bisher kennen.
Wenn Sie DynamoDB für einen neuen Workload evaluieren – oder bereits Tabellen in Produktion haben und die Kosten schwerer zu erklären sind, als Ihnen lieb ist –, dann ist das genau die Art von Arbeit, die DoiT Woche für Woche mit AWS-Kunden leistet. Unser Team aus über 100 Cloud-Experten hilft Ihnen, Zugriffsmuster zu validieren, Designprobleme früh zu erkennen und das Maximum aus den Services herauszuholen, für die Sie bereits zahlen. Buchen Sie eine Demo.