🗄️ Bases de données

database-dynamodb-guide

Modélisation et requêtes DynamoDB incluant single-table design, GSI, LSI, capacity modes et streams.

⚡ Installation & lancement en 1 commande

Copiez-collez dans votre terminal : le skill s'installe dans ~/.claude/skills et Claude Code se lance directement dessus.

macOS / Linux
curl -fsSL https://raw.githubusercontent.com/khalilbenaz/claude-skills-collection/main/install.sh | sh -s -- database-dynamodb-guide --launch
Windows (PowerShell)
iex "& { $(iwr -useb https://raw.githubusercontent.com/khalilbenaz/claude-skills-collection/main/install.ps1) } database-dynamodb-guide -Launch"

🚀 Déjà installé ?

claude "/database-dynamodb-guide"

Ou tapez /database-dynamodb-guide dans une session Claude Code, ou décrivez simplement votre besoin — le skill se déclenche automatiquement via le skill-router.

🔑 Déclencheurs automatiques

Le skill s'active automatiquement quand votre demande contient :

DynamoDBNoSQL AWSsingle-table designGSI

📦 Installation manuelle

git clone https://github.com/khalilbenaz/claude-skills-collection.git cp -r claude-skills-collection/skills/database-dynamodb-guide ~/.claude/skills/

Payload du plugin : skills/database-dynamodb-guide · source éditable : database-skills/dynamodb-guide

📖 Manuel

DynamoDB Guide

1. Identifier les access patterns (obligatoire en premier)

Avant tout schéma, lister chaque pattern : entité cible, clés de filtrage, tri, cardinalité, fréquence.

PatternPKSKIndex
Récupérer user par IDUSER#<userId>#PROFILEtable
Commandes d'un user (par date)USER#<userId>ORDER#<isoDate>table
Commandes par statutSTATUS#<status><isoDate>GSI1
Produits par catégorieCAT#<categoryId>PRODUCT#<productId>GSI2

Règle : ne jamais commencer par le modèle relationnel ; partir exclusivement des patterns de lecture.


2. Concevoir le single-table design

Table: MyApp
PK (partition key): string
SK (sort key):      string
GSI1PK / GSI1SK:   attributs surchargés pour GSI1
entity_type:        "USER" | "ORDER" | "PRODUCT" (facilite les projections)
ttl:                epoch unix (optionnel, activation TTL côté table)

Préfixes d'entité conseillés : USER#, ORDER#, PRODUCT#, SESSION#, STATUS#.

Modèle overloaded key (un item = plusieurs types) :

# Python (boto3) — créer un user
table.put_item(Item={
    "PK": f"USER#{user_id}",
    "SK": "#PROFILE",
    "entity_type": "USER",
    "email": email,
    "created_at": iso_now,
})

# Créer une commande liée à ce user
table.put_item(Item={
    "PK": f"USER#{user_id}",
    "SK": f"ORDER#{order_date}#{order_id}",
    "entity_type": "ORDER",
    "GSI1PK": f"STATUS#{status}",
    "GSI1SK": order_date,
    "amount": Decimal("99.90"),
})

3. Définir les index secondaires

GSI (Global Secondary Index) — clé de partition différente de la table principale, bonne pour les lookups cross-partition.

# Créer un GSI via AWS CLI
aws dynamodb update-table \
  --table-name MyApp \
  --attribute-definitions AttributeName=GSI1PK,AttributeType=S AttributeName=GSI1SK,AttributeType=S \
  --global-secondary-index-updates '[{
    "Create": {
      "IndexName": "GSI1",
      "KeySchema": [
        {"AttributeName":"GSI1PK","KeyType":"HASH"},
        {"AttributeName":"GSI1SK","KeyType":"RANGE"}
      ],
      "Projection": {"ProjectionType":"ALL"},
      "BillingMode": "PAY_PER_REQUEST"
    }
  }]'

LSI (Local Secondary Index) — même PK que la table, SK alternatif. Doit être déclaré à la création de la table, impossible d'en ajouter après.

Critères de choix :

BesoinChoix
Tri alternatif dans la même partitionLSI
Lookup sur une entité différenteGSI
Accès fortement cohérentLSI (cohérence forte possible)
Scalabilité indépendanteGSI

Limite : max 20 GSI par table, max 5 LSI par table.


4. Choisir le mode de capacité

CritèreOn-DemandProvisioned + Auto-scaling
Trafic imprévisible / startuprisque throttling
Charge stable et prévisibletrop cher
Burst soudainconfigurer burst capacity
Contrôle budgétaire strictdifficile
# Passer en provisioned avec auto-scaling (target 70%)
aws application-autoscaling register-scalable-target \
  --service-namespace dynamodb \
  --resource-id "table/MyApp" \
  --scalable-dimension "dynamodb:table:ReadCapacityUnits" \
  --min-capacity 5 --max-capacity 1000

aws application-autoscaling put-scaling-policy \
  --policy-name "DynamoDBReadScaling" \
  --service-namespace dynamodb \
  --resource-id "table/MyApp" \
  --scalable-dimension "dynamodb:table:ReadCapacityUnits" \
  --policy-type TargetTrackingScaling \
  --target-tracking-scaling-policy-configuration \
    '{"TargetValue":70.0,"PredefinedMetricSpecification":{"PredefinedMetricType":"DynamoDBReadCapacityUtilization"}}'

5. Implémenter les opérations CRUD

import boto3
from boto3.dynamodb.conditions import Key, Attr

dynamodb = boto3.resource("dynamodb")
table = dynamodb.Table("MyApp")

# Query (toujours préférer à Scan)
resp = table.query(
    KeyConditionExpression=Key("PK").eq(f"USER#{user_id}") & Key("SK").begins_with("ORDER#"),
    ScanIndexForward=False,   # tri DESC
    Limit=20,
    ExclusiveStartKey=last_key,  # pagination
)
items, next_key = resp["Items"], resp.get("LastEvaluatedKey")

# Query sur GSI
resp = table.query(
    IndexName="GSI1",
    KeyConditionExpression=Key("GSI1PK").eq(f"STATUS#PENDING"),
)

# Écriture conditionnelle (optimistic locking)
table.put_item(
    Item={...},
    ConditionExpression=Attr("PK").not_exists(),  # insert only
)

# Transaction atomique (jusqu'à 100 items, 4 MB)
dynamodb.meta.client.transact_write(Items=[
    {"Put": {"TableName": "MyApp", "Item": {...}}},
    {"Update": {"TableName": "MyApp", "Key": {...},
                "UpdateExpression": "SET balance = balance - :amount",
                "ConditionExpression": "balance >= :amount",
                "ExpressionAttributeValues": {":amount": Decimal("50")}}},
])

6. Configurer DynamoDB Streams

# Activer le stream NEW_AND_OLD_IMAGES
aws dynamodb update-table \
  --table-name MyApp \
  --stream-specification StreamEnabled=true,StreamViewType=NEW_AND_OLD_IMAGES

Cas d'usage courants :

View types : KEYS_ONLY (minimal) | NEW_IMAGE | OLD_IMAGE | NEW_AND_OLD_IMAGES (audit complet).


7. Optimiser les coûts et performances

# DAX (DynamoDB Accelerator) — microseconde latency, drop-in replacement
import amazondax
dax = amazondax.AmazonDaxClient(endpoints=["my-dax.xxx.dax-clusters.amazonaws.com:8111"])
table = dax.Table("MyApp")

# TTL — expiration automatique (epoch unix)
table.put_item(Item={
    "PK": f"SESSION#{session_id}",
    "SK": "#DATA",
    "ttl": int(time.time()) + 3600,  # expire dans 1h
    ...
})

Autres leviers :


8. Tester et valider

# DynamoDB Local (Docker)
docker run -p 8000:8000 amazon/dynamodb-local

# Pointer boto3 sur local
boto3.resource("dynamodb", endpoint_url="http://localhost:8000")

# NoSQL Workbench — visualiser le modèle et simuler les queries (GUI)
# Téléchargement : https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/workbench.settingup.html

Checklist de validation :


Garde-fous / anti-patterns / pièges

Anti-patternConséquenceRemède
Scan en productionFull table read, coûts explosifsRemodéliser avec GSI
PK à faible cardinalité (ex: status)Hot partition, throttlingAjouter un suffixe de sharding STATUS#<hash%10>
Modéliser comme une BDD relationnelleJointures impossibles, ScansPartir des access patterns
Item > 400 KBErreur ItemSizeTooLargeExternaliser vers S3
Trop de GSI (> 5-6)Coûts WCU doublés, complexitéFusionner via attributs surchargés
Lectures fortement cohérentes partout2x le coût en RCUUtiliser eventual consistency sauf besoin strict
Ignorer LastEvaluatedKeyRésultats tronqués silencieuxToujours paginer jusqu'à null
Transactions > 25 items (ancien quota)Erreur — nouveau quota 100 items 4 MBVérifier version SDK et quota région

Bonnes pratiques 2026