Questo file documenta questa architettura così come esiste effettivamente nel codice, verificata file per file al 23 agosto 2026 - diagrammi, figure ed estratti inclusi. Questa è la pagina pilastro del cluster “Rust Engineering”: fornisce la panoramica e i collegamenti alle analisi tecniche approfondite (Axum, Cargo workspace, gateway, PostgREST, pg_graphql e il resto del file) pubblicate o in fase di pubblicazione. Per il confronto completo del prodotto con un BaaS concorrente, vedere il nostro confronto Aurabase vs Supabase.
L'essenziale
- Single Workspace Cargo: 18 crate (11 servizi aziendali,
auraCLI, 5 librerie condivise, Rust SDK) compilati insieme da un singolocargo build --workspace. - Il codice aziendale pesa circa 274.000 righe di Rust (misurate tramite
find+wc -l, 23 agosto 2026), distribuite su queste 18 casse. - Il gateway (
aura-gateway) separa due piani: dati (SDK, porta 8080) e gestione (Studio, porta 8090), ciascuno con il proprio stack middleware e autenticazione. - Aurabase non riscrive PostgREST: il vero binario upstream (v12.2.8) viene eseguito per tenant, orchestrato dai servizi Rust: il valore aggiunto è attorno ad esso, non invece.
- L'unico allontanamento degno di nota dal puro Rust: il runtime predefinito di Edge Functions (modalità
deno) è un servizio TypeScript dedicato basato su V8 Isolates; esiste un secondo percorso, nativo e in Rust tramite Wasmtime, per la modalitàwasm.
Ciò che distingue Aurabase da un servizio assemblato BaaS per servizio
La maggior parte dei BaaS Postgres open source confeziona i propri servizi in più lingue. Questo non è un giudizio di valore: è un fatto architettonico che ha conseguenze concrete: tante catene di compilazione, convenzioni di errore e logiche di autenticazione da mantenere sincronizzate quante sono le lingue in gioco.
In Aurabase, il livello di prodotto che scriviamo e manteniamo noi stessi (gateway, autenticazione, database, tempo reale, archiviazione, notifiche, intelligenza artificiale, provisioning, gestione degli account) è un unico spazio di lavoro Cargo, un unico linguaggio, un'unica catena di creazione. Questa è la scelta che questo fascicolo documenta.
"Nucleo unificato" non significa che tutto ciò che viene eseguito in produzione è Rust. Come ogni Postgres BaaS, anche Aurabase si basa su elementi costitutivi open source che non ha scritto: PostgreSQL stesso, PostgREST, NATS. La differenza strutturale con uno stack eterogeneo non riguarda questi elementi costitutivi condivisi, ma riguarda lo strato di prodotto che li orchestra. Le sezioni seguenti descrivono in dettaglio dove passa esattamente questo confine, inclusa l'unica vera eccezione che abbiamo riscontrato durante l'auditing del codice (Funzioni Edge, sezione 09).
18 casse, una catena di compilazione
La root Cargo.toml dichiara un'area di lavoro Cargo nel risolutore v2 con 18 membri: 11 servizi aziendali, aura-cliCLI, 5 librerie condivise e aurabase-rsSDK. Ecco l'elenco effettivo, come appare nel repository.
Le dipendenze condivise risiedono in [workspace.dependencies]: Axum 0.8 (con WebSocket, multipart, macro), Tokio, Tower/Tower-HTTP, SQLx 0.8 (Postgres + MongoDB tramite mongodb per motore NoSQL secondario), async-nats 0.47, sqlparser 0.53 (convalida SQL di NL2SQL), oauth2 5, jsonwebtoken 10 e due librerie di prestazioni presenti in quasi tutti i servizi: mimalloc come allocatore globale e moka/dashmap per la cache in memoria.
Il profilo di rilascio documenta una scelta presunta: panic = "unwind" anziché "abort". Il commento del file si spiega da sé: il panico in un gestore Axum/Tokio viene isolato dal runtime (la richiesta interessata restituisce 500) invece di interrompere l'intero processo e tagliare le richieste concorrenti. Il miglioramento delle prestazioni diabort (circa dall'1 al 2% di RPS) non vale la perdita di isolamento, secondo la stessa nota. Si tratta di un compromesso tra affidabilità e velocità documentato nel codice, non un'affermazione di marketing.
Un singolo cargo build --workspace compila il tutto. Un singolo cargo test --workspace esegue l'intera suite di test. Un singolo cargo clippy --workspace --all-targets -- -D warnings uniforma l'intero prodotto con le stesse regole. I dettagli di questa struttura - ereditarietà delle dipendenze, grafico interno tra librerie e servizi, insidie che abbiamo incontrato durante la sua crescita - sono oggetto di un articolo dedicato: Architettura dello spazio di lavoro Cargo, come strutturare un backend Rust multi-servizio.
Linee Rust per servizio (find services -name '*.rs' | xargs wc -l, 23 agosto 2026):
controllo dell’aura
36 024
aura-db
30 255
aura-auth
28 431
fornitore dell'aura
28 271
notifiche dell'aura
18 498
avrà
18 305
aura-gateway
16 938
aura in tempo reale
16 799
immagazzinamento dell'aura
13 747
funzioni dell'aura
11 619
aura-migratore
538
Escluse le librerie condivise (aura-db-adapters: 24.725 linee, aura-core: 7.259, aura-migrations: 3.641, aura-crypto: 2.718, aura-telemetry: 201), la CLI (aura-cli: 9.845) e l'SDK di Rust (aurabase-rs: 6.363). aura-migrator, un lavoro di migrazione monouso e non un server HTTP di lunga durata, rimane deliberatamente il servizio più piccolo nell'area di lavoro.
11 servizi aziendali, ciascuno un server Axum autonomo
Ogni servizio è un binario Axum/Tokio indipendente, con la propria configurazione e porta. Dieci degli undici espongono /health e /metrics e dichiarano mimalloc come allocatore globale: l'unica eccezione, aura-migrator, è un lavoro a scopo singolo anziché un server in esecuzione continua.
| aura-gateway | Gateway a doppio piano (dati:8080, gestione:8090): proxy per tutti gli altri servizi. |
|---|---|
| aura-auth | Autenticazione: JWT, 15 provider OAuth denominati + OIDC generico per progetto, sessioni, MFA. |
| aura-db | API del database: gestione/ricaricamento PostgREST per tenant, adattatori Postgres e MongoDB, CDC. |
| fornitore dell'aura | Ciclo di vita del progetto: cluster CNPG dedicati o condivisi, ruoli, PostgREST per tenant. |
| aura in tempo reale | WebSocket e SSE, trasmissione CDC, presenza tra istanze tramite NATS JetStream KV. |
| immagazzinamento dell'aura | Oggetti compatibili S3 (MinIO), policy RLS trasferibili da Postgres. |
| funzioni dell'aura | Funzioni Edge: distribuzione, processi, cron, runtime Wasmtime nativo (vedere sezione 09). |
| notifiche dell'aura | E-mail, push, webhook in uscita. |
| avrà | Gateway NL2SQL, RAG e LLM (OpenAI nativo, Anthropic, Gemini + qualsiasi endpoint compatibile con OpenAI). |
| aura-migratore | Motore di migrazione: singola origine dello schema di mantenimento riprodotto ad ogni provisioning. |
| controllo dell’aura | Piano di gestione: account sviluppatore, organizzazioni, fatturazione, API Studio. |
La aura CLI (≈ 9.800 righe) comunica con le stesse API degli SDK: non ha un percorso privilegiato. Il riferimento completo per ciascun servizio si trova nella documentazione dell'architettura e nel riferimento CLI .
5 casse che evitano la deriva tra i servizi
In uno stack poliglotta, una regola di sicurezza – formato degli errori, protezione SSRF, limitazione della velocità – deve essere reimplementata in ciascuna lingua e quasi sempre cambia nel corso dei mesi. Aurabase lo codifica una volta, in una libreria dello spazio di lavoro, consumata da tutti i servizi interessati.
| nucleo dell'aura | 7 259 l. | Primitive condivise: errori, busta di risposta API, attestazioni JWT, autenticazione interna da servizio a servizio, helper NATS, limitazione della velocità, client HTTP protetto SSRF, interruttore automatico, risoluzione tenant, misurazione. |
|---|---|---|
| adattatori aura-db | 24 725 l. | Tratto per adattare il database unificato, le implementazioni Postgres e MongoDB utilizzate da aura-db. |
| aura-cripto | 2 718 l. | Hashing delle password, generazione di token, firma/convalida JWT, crittografia a livello di campo. |
| migrazioni dell'aura | 3 641 l. | Motore di migrazione: origine unica dello schema tenant, riprodotta dal provider (non le migrazioni/cartelle specifiche per ciascun servizio). |
| aura-telemetria | 201 l. | Configurazione OpenTelemetry + tracciamento, condivisa dagli 11 servizi. |
Conseguenza diretta: una patch di sicurezza in aura-core (la protezione SSRF, ad esempio) si propaga a ciascun servizio consumer nel successivo cargo build, non attraverso cinque patch separate in cinque lingue.
Doppio piano: traffico SDK e traffico Studio
aura-gateway separa due superfici che non hanno né gli stessi client né lo stesso modello di autenticazione. Il piano dati (porta 8080, variabile GATEWAY_PORT) riceve traffico SDK/app, autenticato dalla chiave API (apikey, X-API-Key o ?apikey=). Il piano di gestione (porta 8090, MANAGEMENT_PORT) riceve il traffico Studio/amministratore, autenticato da una console JWT (Authorization: Bearer).
Ogni piano trasporta il proprio stack di middleware - identificazione delle query, registro di accesso, limite di velocità, autenticazione (specifica del piano), interruttore di circuito, quindi proxy - implementato in moduli separati (middleware/rate_limit.rs, middleware/circuit_breaker.rs, middleware/auth_data_plane.rs, middleware/auth_management_plane.rs) piuttosto che una singola catena condivisa accidentalmente tra due superfici che non dovrebbero fidarsi l'una dell'altra allo stesso modo. modo.
L'ordine esatto dei middleware, il rate limiting per target e il proxy NATS/HTTP sono oggetto di un articolo dedicato: dual-plane gateway, progettare un gateway API data-plane/management-plane in Rust.
Perché Aurabase non reimplementa PostgREST in Rust
L'API REST autogenerata utilizzata dall'SDK non è un modulo Rust interno: è il vero binario upstream PostgREST (postgrest/postgrest:v12.2.8), distribuito in 2 repliche per progetto dedicato (deploy/cnpg/tenant-postgrest.yaml), co-localizzato con l'istanza CNPG del tenant. aura-provisioner crea questa distribuzione e aura-db analizza il suo endpoint OPTIONS dopo ogni ricaricamento dello schema per confermare che PostgREST ha preso in considerazione la modifica DDL.
Si tratta di una scelta architetturale scontata, non di una scorciatoia: PostgREST è un progetto maturo e ampiamente adottato, la cui riscrittura del comportamento poco a poco in Rust non porterebbe a nulla. Il lavoro su Rust di Aurabase è incentrato su routing multi-tenant, provisioning, isolamento della rete da parte di NetworkPolicy, autenticazione condivisa con il gateway, ricaricamento dello schema orchestrato, non all'interno del motore di query stesso. Ciò che copre realmente questa compatibilità, e dove si ferma, è oggetto di un articolo separato: PostgREST, compatibilità effettiva e alternative.
Stessa logica sul lato GraphQL: l'estensione Postgres pg_graphql (pacchetto .deb precompilato, v1.6.1) è installata nell'immagine CNPG dedicata e attivata su richiesta per progetto tramite l'endpoint POST /v1/control/projects/{project_id}/graphql/enable - non è nemmeno un motore GraphQL riscritto. Dettagli e confronto onesto con Hasura e PostGraphile: API GraphQL nativa su Postgres con pg_graphql.
Ruolo RLS e autenticatore, non un livello di applicazione
L'isolamento multi-tenant non si basa su un filtro WHERE tenant_id = ? aggiunto da un ORM dell'applicazione: ogni richiesta passa attraverso il ruolo aura_authenticator, che esegue un SET LOCAL ROLE tenant_<uuid> con ambito transazione prima di eseguire la richiesta, esattamente il modello che PostgREST stesso si aspetta. La sicurezza a livello di riga fa il resto, a livello del motore, non a livello del codice aziendale.
Non tutti i progetti condividono la stessa topologia Postgres. Il codice aura-provisioner espone un tipo ProjectInstanceKind con almeno due varianti reali: FullyDedicated (istanza CNPG interamente dedicata al progetto) e SharedClusterDedicated (schema isolato da RLS su un cluster CNPG condiviso). Il piano sottoscritto determina la topologia: non è una promessa uniforme di una “base dedicata per tutti”.
L'argomento “perché una base dedicata per progetto piuttosto che un puro isolamento applicativo” è oggetto di un articolo dedicato: RLS e base dedicata per progetto. La documentazione Sicurezza a livello di riga copre l'implementazione pratica.
Nucleo NATS, non JetStream: messaggistica asincrona tra servizi
Dieci degli undici servizi aziendali dichiarano async-nats come dipendenza diretta nel loro Cargo.toml – solo aura-migrator ne fa a meno. Ciò che il nome di questa cassa non dice: questi servizi quasi ovunque utilizzano l'API pub/sub coredi NATS (Client::publish / publish_with_headers, consegna al massimo una volta senza persistenza o riproduzione), non JetStream. Questo è il caso verificato nel codice per i tre usi che contano di più: la distribuzione del CDC PostgreSQL su aura-realtime, la notifica dei lavori Edge Functions in aura-functions (il DLQ stesso risiede in Postgres, non in NATS) e gli eventi di provisioning tra aura-provisioner e il resto della flotta.
JetStream, la modalità di persistenza e flussi denominati di NATS, viene visualizzato solo in una posizione verificata nel monorepo: la presenza tra istanze KV Store in aura-realtime (bucket aura_presence, archivio di memoria, 60 secondi max_age), che sincronizza chi è connesso a quale canale su più istanze di ws-front: uno stato condiviso tra istanze, non un flusso di eventi da riprodurre. Nessun flusso JetStream persistente è stato trovato altrove nell'area di lavoro. I dettagli della pipeline CDC - wal2json, elezione di un cdc-worker unico da parte di Lease Kubernetes, fan-out core NATS alle repliche ws-front, nuova verifica RLS da parte dell'abbonato - sono oggetto di un articolo dedicato: ha trasmesso il CDC PostgreSQL con NATS. La documentazione Realtime copre l'utilizzo sul lato SDK.
Edge Functions: due runtime per due esigenze
Questa è la sfumatura più importante di questo file e l'unico vero allontanamento dal puro Rust nel codice prodotto Aurabase. Ogni funzione trasporta un campo runtime che vale "wasm" o "deno". Il gestore di invocazione sceglie di conseguenza il percorso di esecuzione: lo snippet effettivo, commentato nel codice stesso:
La modalità wasm è nativa: aura-functions dipende direttamente da Wasmtime (versione 43, presenta async e cranelift) ed esegue il modulo nello stesso processo Rust, con conteggio del carburante, interruzione per epoca e limitazione della memoria tramite StoreLimits. La modalità deno — quella utilizzata per impostazione predefinita nell'editor di Studio, per una compatibilità quasi diretta Deno.serve() con il codice Supabase esistente — delega l'esecuzione a aura-edge-runtime, un servizio TypeScript separato di circa 550 righe, modellato esplicitamente — lo stesso commento dell'intestazione del file sorgente lo cita — su supabase/edge-runtime (licenza MIT), che isola ogni invocazione nel proprio Isolamento V8.
Il controllo (distribuzione, autorizzazioni, lavori, cron, quote) rimane interamente in Rust in aura-functions. Solo l'esecuzione del codice utente in modalità deno fa uscire dal binario Rust. Si tratta di un compromesso ingegneristico difendibile (gli Isolati V8 sono ciò che Deno fornisce nativamente per questo livello di sandboxing), non un'omissione che preferiamo tacere. Il confronto Wasmtime vs Wasmer e l'analisi dell'avvio a freddo di WebAssembly, presto disponibili in questo file, approfondiranno questo argomento.
Per la documentazione procedurale di entrambi i percorsi di distribuzione, vedere Edge Functions. Per il playbook sulla migrazione di Deno da Supabase, consulta Migrare un progetto Supabase ad Aurabase, che ha già documentato questa distinzione prima di questo file.
Ciò che questo cuore unificato cambia concretamente per te
Se chiami l'API semplicemente tramite un SDK, questa architettura è invisibile: questo è l'obiettivo. È importante principalmente per tre tipi di pubblico: coloro che valutano l'affidabilità operativa di un backend multi-tenant prima di migrarvi i dati di produzione, coloro che intendono contribuire al repository (MIT, monorepo singolo) e coloro che vogliono capire perché una patch di sicurezza sul lato Aurabase si diffonde rapidamente anziché lentamente.
Concretamente: un singolo IC (cargo build --workspace, cargo test --workspace, cargo clippy --workspace --all-targets -- -D warnings) copre il 90% o più della superficie del prodotto. Una revisione del codice su aura-core influisce potenzialmente su dieci servizi contemporaneamente: in meglio (una correzione non si perde per strada) e in peggio (una modifica scarsamente isolata si diffonde altrettanto rapidamente). È un compromesso, non una soluzione magica, ed è proprio per questo che documentiamo l'architettura effettiva anziché un riepilogo di marketing.
Il resto del file di Rust Engineering
Questa pagina del pilastro si collega alle analisi tecniche del cluster, man mano che vengono pubblicate. Stato attuale al momento della pubblicazione di questa pagina: i collegamenti diventano attivi non appena l'articolo corrispondente è online.
Cluster A: struttura e architettura
Axum vs Actix-web: quale framework per un backend Rust in produzione?Pubblicato
Architettura del workspace Cargo: come strutturare un backend Rust multiservizioPubblicato
Gateway dual-plane: progettazione di un gateway API piano dati/piano di gestione in RustPubblicato
Cluster B: API autogenerata su Postgres
PostgREST: cosa copre realmente la compatibilità e quali alternative esistonoPubblicato
API GraphQL nativa su Postgres con pg_graphql: cosa Hasura e PostGraphile non fanno lo stessoPubblicato
RLS e base dedicata per progetto: la scelta dell'isolamento multi-tenant di AurabasePubblicato
Cluster C: tempo reale e messaggistica
Distribuisci PostgreSQL CDC con NATS: architettura in tempo realePubblicato
Cluster D: WebAssembly di funzioni Edge
| Wasmtime vs Wasmer: quale runtime WebAssembly per Edge Functions in produzione | Prossimamente |
|---|---|
| Funzioni Edge in Rust/WASM rispetto a Cloudflare Workers e Vercel Edge | Prossimamente |
| WebAssembly con avvio a freddo: cosa dicono veramente i benchmark (e cosa non possiamo ancora dire) | Prossimamente |
Cluster E – Migrazione e alternative
Migra un progetto Supabase su Aurabase senza riscrivere le tue policy RLSPubblicato
Self-hosting sovrano: posizionamento di Aurabase contro BaaS nativo di Rust Disponibile a breve