DynamoDB nach einem sich ändernden Attribut sortieren
Du modellierst einen Sort Key um ein Attribut, um Items in seiner Ordnung zu querien — dann ändert sich das Attribut. Der Status eines Tickets, der State einer Order, die Priority einer Task. DynamoDBs Regel: du kannst ein Key-Attribut nicht in Place updaten. Ein Primary Key ist für die Lebensdauer des Items immutable. Ändere einen Wert, der Teil des Keys ist, und du editierst kein Item — du bewegst es, und DynamoDB lässt dich das explizit tun.
Kannst du einen DynamoDB-Sort-Key ändern?
Nein. Ein Sort Key ist Teil des Primary Key, und DynamoDB-Key-Attribute sind
immutable — UpdateItem kann keinen Partition- oder Sort-Key-Wert editieren, und
es gibt keine „Move Item“-Operation. Um ihn zu ändern, lösche das alte Item und
putte ein neues, oder halte den volatilen Wert stattdessen auf einem
GSI-Sort-Key.
- Key-Attribute sind immutable. Du kannst keinen Partition- oder Sort-Key-
Wert
UpdateItemen — DynamoDB hat keine „Move Item“-Operation. - Um einen Key-Wert zu ändern, löschst du das alte Item und puttest ein neues — idealerweise in einer Transaction, damit es atomar ist.
- Besser: halte den volatilen Wert vom Base-Table-Key fern und lege ihn auf einen GSI-Sort-Key — GSI-Keys können sich ändern, weil das Updaten des Base-Items den Index-Eintrag nur neu propagiert.
- Wähle Sort Keys, die sich nicht ändern (Timestamps, immutable Ids), wann immer das Access Pattern es erlaubt.
Das Problem: ein Status, nach dem du sortieren willst, der sich ständig ändert
Angenommen, du betreibst einen Support-Desk und willst Tickets eines Teams nach Status geordnet listen, also legst du Status in den Sort Key:
PK: TEAM#7 SK: STATUS#open#TICKET#8842Jetzt bewegt sich das Ticket zu pending. Du würdest gerne einfach den Sort Key
per UpdateItem auf STATUS#pending#TICKET#8842 setzen — aber DynamoDB
rejectet jeden Write, der ein Key-Attribut ändert. Der Key ist die Adresse des
Items; du kannst die Adresse nicht in Place editieren. Der Status, nach dem du
sortieren wolltest, ist genau das, was nicht stillsitzt.
Option 1: löschen und neu erstellen (atomar)
Wenn der Wert im Base-Table-Key leben muss, heißt ihn zu ändern, das alte Item zu entfernen und das neue zu schreiben:
1. DeleteItem PK=TEAM#7 SK=STATUS#open#TICKET#8842
2. PutItem PK=TEAM#7 SK=STATUS#pending#TICKET#8842 (same attributes)Tu es in einem TransactWriteItems, sodass Delete
und Put entweder beide succeeden oder beide failen — sonst verliert ein Crash
dazwischen das Ticket oder dupliziert es. Das funktioniert, aber jede Status-
Änderung sind jetzt zwei Writes plus eine Transaction; fine für gelegentliche
Änderungen, teuer für heiße.
Option 2: den mutablen Wert vom Base-Key fernhalten (bevorzugt)
Mach den Base-Table-Key etwas Immutables (die Ticket-Id) und lege den volatilen, sortierbaren Wert auf einen GSI-Sort-Key.
Base: PK: TICKET#8842 status: "open" teamId: TEAM#7
GSI: GSI1PK: TEAM#7 GSI1SK: STATUS#open#TICKET#8842Status zu ändern ist jetzt ein plaines UpdateItem auf dem status-Attribut des
Base-Items — das DynamoDB erlaubt, weil status kein Base-Table-Key ist.
DynamoDB propagiert den GSI-Eintrag dann automatisch neu an seine neue
sortierte Position. Ein API-Call, mit Atomicity für dich gehandelt — keine
Transaction, kein Delete-Tanz (unter der Haube löscht DynamoDB trotzdem den alten
Index-Eintrag und schreibt den neuen, also kostet eine indexierte Änderung ~3 Write
Units gegen ~4 einer transactional Delete-and-Put).
Der GSI ist eventuell konsistent und kostet extra Storage/Writes — aber für einen Wert, der sich oft ändert, ist das etwas günstiger (~3 vs 4 Write Units) und viel einfacher als Delete-and-Recreate bei jeder Änderung.
Die Keys in DynoTable designen
Baue und preview die Key Conditions für den Base-Read und den GSI-Read im DynamoDB Expression Builder.
In DynoTable wählst du dann, durch welchen Index eine Query läuft, und siehst den volatilen Wert auf dem GSI sortieren, während das Base-Item seinen immutable Key behält — beide Reads Side by Side auf echten Daten.

Fallstricke + nächste Schritte
- Versuche nie, ein Key-Attribut zu
UpdateItemen — es wird rejected; Key- Werte sind für die Lebensdauer des Items fix. - Wenn du es bewegen musst, tu Delete+Put in einer Transaction — nie als zwei ungeschützte Writes.
- Bevorzuge immutable Base-Keys + einen GSI für jedes Attribut, nach dem du sortierst und das du mutierst.
- Vergiss GSI Eventual Consistency nicht — der neu sortierte Eintrag erscheint nach einer kurzen Propagation-Verzögerung.
- Verwandt: Sort-Key-Strategien, GSI vs LSI, Transactions.
Willst du sehen, wie ein mutables Attribut auf einem GSI versus der Base Table sortiert? Lade DynoTable herunter und erkunde deine Indexes direkt.
Write-Kosten: Delete-and-Put vs GSI-Update
Grobe WCU-Vergleiche für ein 1-KB-Ticket-Item in us-east-1 On-Demand (echte
Abrechnung folgt AWS-Rounding-Regeln):
| Pattern | API-Calls | Typischer WCU-Impact |
|---|---|---|
| Transactional Delete + Put auf Base-Key | TransactWriteItems (2 Ops) | ~2× Item-Größe pro Op in Transaction-Pricing |
status-Attribut updaten; GSI propagiert neu | Ein UpdateItem | Base-Write + GSI-Write (~2 WCU für 1-KB-Item + projezierten Attrs) |
Der GSI-Pfad vermeidet Application-Level-Orchestrierung und eliminiert das Fenster, in dem ein Crash zwischen Delete und Put die Row verliert. Du tauschst Eventual Consistency auf dem Index-Read gegen einfachere Writes.
Modelliere deine Item-Größe und Update-Rate im Pricing Calculator, wenn Status-Änderungen viele Male pro Minute feuern.
Sparse GSI für status-sortierte Listen
Wenn nur offene Tickets eine status-sortierte Queue brauchen, nutze einen
Sparse Index: schreibe GSI1PK = TEAM#7 und
GSI1SK = STATUS#open#... nur solange status = open. Wenn das Ticket schließt,
entferne oder omitte die GSI-Key-Attribute beim Update — das Item fällt aus dem
Index, ohne Delete-and-Put auf dem Base-Sort-Key.
Das hält den Index klein und vermeidet, geschlossene Tickets zu indexieren, die du nie listest.
Immutable Base-Keys, die du bevorzugen solltest
| Volatiles Feld | Base-Table-SK | Besserer Base-SK | Volatiles Feld lebt auf |
|---|---|---|---|
| Order-Status | STATUS#shipped#ORD#99 | ORD#99 | GSI-Sort oder Attribut |
| Task-Priority | P#1#TASK#12 | TASK#12 | GSI-Sort |
| User Display Name | NAME#alice#USER#5 | USER#5 | Non-Key-Attribut |
Timestamps und immutable Ids (CREATED#2026-06-27T10:00:00Z, TICKET#8842)
machen stabile Base-Sort-Keys, wenn du chronologische Ordnung auf der Base Table
selbst brauchst.
Designe den GSI vor dem Coding
Mappe Access Patterns im
Single-Table-Design-Tool — gib „liste offene
Tickets per Team, Priority-Ordnung“ ein und inspiziere die vorgeschlagenen
GSI1PK-/GSI1SK-Templates. Dann baue die Key Condition im
Expression Builder und emitte eine paginierte
Query mit dem Query Builder für Integrationstests.
Read-your-writes nach Status-Änderung
Nach UpdateItem zeigt ein stark konsistenter Read auf der Base Table den
neuen status sofort. Eine Query auf dem GSI kann kurz nachhinken. UI-Flows, die
zu einer GSI-sortierten Queue redirecten, sollten stale Rows tolerieren oder vom
Base Table per Id re-fetchen, wenn Precision zählt.


