DynamoDB Local è stato il sostituto da laptop per AWS DynamoDB dal 2013. È un JAR Java, funziona in memoria o su un file SQLite, accetta quasi qualsiasi forma di richiesta, non ha una vera autenticazione e tratta gli Stream in modo piuttosto approssimativo. Va bene per i test unitari. Inizia a scricchiolare nel momento in cui il tuo codice fa qualcosa oltre PutItem e GetItem.

ExtendDB v0.1.0 è appena stato rilasciato. È un'implementazione clean-room del protocollo wire DynamoDB, scritta in Rust da ingegneri AWS, con PostgreSQL come backend, Apache 2.0. La promessa è "DynamoDB Local, ma puoi prenderlo sul serio." Questo post è un'analisi pratica per verificare se regge, eseguita come laboratorio fianco a fianco su un singolo Mac.

Cosa è effettivamente ExtendDB

ExtendDB non è un fork di DynamoDB. Non contiene codice sorgente di DynamoDB. Quello che fa è parlare il protocollo wire di DynamoDB (il dispatch JSON-1.0 X-Amz-Target che usano gli AWS SDK), quindi un client boto3 o AWS CLI esistente può essere puntato a un endpoint ExtendDB con una sola modifica di flag e funziona, senza modifiche necessarie.

Sotto il cofano è un piccolo e focalizzato workspace Rust:

flowchart LR
    bin[extenddb<br/>CLI + daemon] --> server[extenddb-server<br/>HTTP + console]
    server --> engine[extenddb-engine<br/>gestori op DynamoDB]
    server --> auth[extenddb-auth<br/>SigV4 + policy IAM]
    engine --> core[extenddb-core<br/>tipi, espressioni]
    engine --> storage[extenddb-storage<br/>definizioni trait]
    storage --> pg[extenddb-storage-postgres<br/>backend PostgreSQL]

Il crate extenddb-storage contiene solo definizioni di trait. extenddb-storage-postgres è l'unica implementazione oggi. La giuntura è abbastanza pulita che un backend diverso (sqlite, foundationdb, qualsiasi cosa) si ridurrebbe principalmente all'implementazione dei trait.

Configurazione del laboratorio

Entrambi i backend girano sullo stesso Mac. Postgres 18.4 da Homebrew, avviato con brew services start postgresql@18. ExtendDB compilato con cargo build --release, poi inizializzato. TLS è obbligatorio. ExtendDB poi gira con extenddb serve su https://127.0.0.1:8000.

DynamoDB Local va accanto in Docker. Un fixture conftest di boto3 alterna tra i due endpoint in base alla variabile d'ambiente LAB_BACKEND, così ogni probe viene eseguito su entrambi i backend senza modifiche al codice.

Parità di base: CRUD funziona bene

La prima cosa da sapere è che le cose facili funzionano. Dieci probe che coprono CreateTable (con GSI), GetItem a consistenza forte, Query su partizione + intervallo sort key, Query sul GSI, Scan con filtro, UpdateItem con SET/REMOVE/ADD combinati più ConditionExpression, DeleteItem con condizione, BatchWriteItem di 25 elementi e TransactWriteItems con un conflitto di condizione intenzionale. Tutti passano su entrambi i backend.

Dove divergono

L'autenticazione è reale, più o meno

ExtendDB cerca la chiave di accesso nel suo archivio IAM e rifiuta quando non esiste. DynamoDB Local non guarda affatto la chiave di accesso. Accetta la richiesta nel momento in cui l'header viene parsato.

Stream con la forma giusta

Entrambi i backend implementano gli Stream. La forma è diversa. ExtendDB partiziona i record degli stream su 4 shard in base all'hash della chiave di partizione, come fa il vero DynamoDB. DynamoDB Local mette tutto su un singolo shard.

TTL con veri record REMOVE

ExtendDB esegue uno sweeper TTL. Inserisci un elemento già scaduto, aspetta, e l'elemento sparisce. Ancora più importante, la cancellazione emette un record di stream con l'identity di servizio specificata: userIdentity = {'PrincipalId': 'dynamodb.amazonaws.com', 'Type': 'Service'}. DynamoDB Local salta tutta questa storia: nessuno sweeper, gli elementi scaduti rimangono nella tabella per sempre.

Isolamento multi-account che funziona

Due account, stesso nome di tabella, righe separate, nessuna interferenza. DynamoDB Local ha esattamente un namespace: stesso nome, stessa tabella.

Sicurezza ai crash e HTTPS

kill -9 del processo ExtendDB a metà scrittura, riavvia, leggi il canary: sopravvive. Durabilità Postgres anziché memoria di processo. HTTPS è obbligatorio.

Quando NON usarlo

  • Non implementati affatto: Global Tables, DAX, PartiQL, auth federata SAML/OIDC, destinazioni streaming Kinesis.
  • Forma diversa: ImportTable / ExportTableToPointInTime vanno su un percorso filesystem locale invece di un bucket S3.
  • Drift del protocollo wire da tenere d'occhio: BatchWriteItem omette UnprocessedItems: {} dalle risposte di successo. I campi userIdentity usano chiavi PascalCase. I consumer degli stream devono svuotare tutti gli shard.
  • Bug v0.1.0: una tabella con stream abilitato non può essere cancellata e ricreata con lo stesso nome durante la stessa vita del server.

Verdetto

Se hai mai scritto codice di test che mascherava DynamoDB Local (mock dell'auth, saltava le asserzioni sugli Stream, stub del TTL) e ti preoccupavi silenziosamente che il servizio reale si comportasse diversamente, ExtendDB è interessante. È il primo sostituto DynamoDB locale che prende sul serio auth, Stream, TTL, isolamento multi-account e durabilità, e il layer di storage è semplice Postgres in cui puoi fare psql.

Per pipeline CI che necessitano di semantiche realistiche di auth e stream, deployment on-prem o air-gapped, e team di sviluppo che hanno perso tempo con "beh, funziona con DynamoDB Local...", v0.1.0 è già uno strumento utile. Per tutto ciò che dipende dalla compatibilità wire byte-esatta con il servizio reale, fai prima il tuo passaggio.