This file documents this architecture as it actually exists in the code, verified file by file as of August 23, 2026 — diagrams, figures and extracts included. This is the pillar page of the “Rust Engineering” cluster: it gives the overview, and links to the in-depth technical analyzes (Axum, Cargo workspace, gateway, PostgREST, pg_graphql, and the rest of the file) published or in the process of being published. For the complete product comparison against a competing BaaS, see our comparison Aurabase vs Supabase.
The essentials
- Single Workspace Cargo: 18 crates (11 business services, the
auraCLI, 5 shared libraries, the Rust SDK) compiled together by a singlecargo build --workspace. - The business code weighs approximately 274,000 lines of Rust (measured via
find+wc -l, August 23, 2026), distributed over these 18 crates. - The gateway (
aura-gateway) separates two planes — data (SDK, port 8080) and management (Studio, port 8090) — each with its own middleware stack and authentication. - Aurabase does not rewrite PostgREST: the real upstream binary (v12.2.8) runs per tenant, orchestrated by Rust services — the added value is around it, not instead.
- The only notable departure from pure Rust: the default runtime of Edge Functions (
denomode) is a dedicated TypeScript service based on V8 Isolates; a second path, native and in Rust via Wasmtime, exists forwasmmode.
What sets Aurabase apart from a BaaS assembled service by service
Most open source Postgres BaaS packages their services in multiple languages. This is not a value judgment — it is an architectural fact that has concrete consequences: as many compilation chains, error conventions and auth logics to keep in synchronization as there are languages in play.
At Aurabase, the product layer that we write and maintain ourselves — gateway, auth, database, real-time, storage, notifications, AI, provisioning, account management — is a single Cargo workspace, a single language, a single build chain. This is the choice that this file documents.
“Unified core” does not mean that everything running in production is Rust. Like any Postgres BaaS, Aurabase also relies on open source building blocks that it did not write: PostgreSQL itself, PostgREST, NATS. The structural difference with a heterogeneous stack does not relate to these shared building blocks — it concerns the product layer which orchestrates them. The following sections detail where exactly this boundary passes, including the only real exception we found when auditing the code (Edge Functions, section 09).
18 crates, one compilation chain
The root Cargo.toml declares a Cargo workspace in resolver v2 with 18 members: 11 business services, the aura-cliCLI, 5 shared libraries, and the aurabase-rsSDK. Here is the actual list, as it appears in the repository.
Shared dependencies live in [workspace.dependencies]: Axum 0.8 (with WebSockets, multipart, macros), Tokio, Tower/Tower-HTTP, SQLx 0.8 (Postgres + MongoDB via mongodb for secondary NoSQL engine), async-nats 0.47, sqlparser 0.53 (SQL validation of NL2SQL), oauth2 5, jsonwebtoken 10, and two performance libs found in almost every service: mimalloc as a global allocator and moka/dashmap for the in-memory cache.
The release profile documents an assumed choice: panic = "unwind" rather than "abort". The file comment is self-explanatory — a panic in an Axum/Tokio handler is isolated by the runtime (the affected request returns 500) instead of bringing down the entire process and cutting off competing requests. The performance gain ofabort (approximately 1 to 2% of RPS) is not worth the loss of insulation, according to this same note. This is a reliability-vs-speed trade-off documented in the code, not a marketing claim.
A single cargo build --workspace compiles the whole thing. A single cargo test --workspace runs the entire test suite. A single cargo clippy --workspace --all-targets -- -D warnings lints the entire product with the same rules. The details of this structure - inheritance of dependencies, internal graph between libs and services, pitfalls that we encountered while growing it - are the subject of a dedicated article: Cargo workspace architecture, how to structure a multi-service Rust backend.
Rust lines by service (find services -name '*.rs' | xargs wc -l, August 23, 2026):
aura-control
36 024
aura-db
30 255
aura-auth
28 431
aura-provisioner
28 271
aura-notifications
18 498
will have
18 305
aura-gateway
16 938
aura-realtime
16 799
aura-storage
13 747
aura-functions
11 619
aura-migrator
538
Excluding shared libs (aura-db-adapters: 24,725 lines, aura-core: 7,259, aura-migrations: 3,641, aura-crypto: 2,718, aura-telemetry: 201), the CLI (aura-cli: 9,845) and the Rust SDK (aurabase-rs: 6,363). aura-migrator, a single-use migration job and not a long-lived HTTP server, deliberately remains the smallest service in the workspace.
11 business services, each a standalone Axum server
Each service is an independent Axum/Tokio binary, with its own configuration and port. Ten of the eleven expose /health and /metrics and declare mimalloc as the global allocator — the only exception, aura-migrator, is a single-purpose job rather than a continuously running server.
| aura-gateway | Dual-plane gateway (data:8080, management:8090): proxy to all other services. |
|---|---|
| aura-auth | Authentication: JWT, 15 named OAuth providers + generic OIDC per project, sessions, MFA. |
| aura-db | Database API: PostgREST management/reload per tenant, Postgres and MongoDB adapters, CDC. |
| aura-provisioner | Project life cycle: dedicated or shared CNPG clusters, roles, PostgREST per tenant. |
| aura-realtime | WebSocket and SSE, CDC broadcast, cross-instance presence via NATS JetStream KV. |
| aura-storage | S3 compatible objects (MinIO), RLS policies transferable from Postgres. |
| aura-functions | Edge Functions: deployment, jobs, cron, native Wasmtime runtime (see section 09). |
| aura-notifications | Email, push, outgoing webhooks. |
| will have | NL2SQL, RAG and LLM gateway (native OpenAI, Anthropic, Gemini + any OpenAI compatible endpoint). |
| aura-migrator | Migration engine: single source of the holding schema replayed at each provisioning. |
| aura-control | Management plan: developer accounts, organizations, billing, Studio API. |
The aura CLI (≈ 9,800 lines) talks to the same APIs as the SDKs — it has no privileged path. The full reference for each service lives in the architecture documentation and the CLI reference.
5 crates that avoid inter-service drift
In a polyglot stack, a security rule — error format, SSRF protection, rate limiting — must be reimplemented in each language, and almost always drifts over the months. Aurabase codes it once, in a workspace lib, consumed by all the services concerned.
| aura-core | 7 259 l. | Shared primitives: errors, API response envelope, JWT claims, internal service-to-service auth, NATS helpers, rate limiting, SSRF protected HTTP client, circuit breaker, tenant resolution, metering. |
|---|---|---|
| aura-db-adapters | 24 725 l. | Trait to adapt unified database, Postgres and MongoDB implementations used by aura-db. |
| aura-crypto | 2 718 l. | Password hashing, token generation, JWT signing/validation, field-level encryption. |
| aura-migrations | 3 641 l. | Migration engine — single source of the tenant schema, replayed by the provisioner (not the migrations/specific folders for each service). |
| aura-telemetry | 201 l. | OpenTelemetry + tracing configuration, shared by the 11 services. |
Direct consequence: a security patch in aura-core — SSRF protection, for example — propagates to each consumer service in the next cargo build, not through five separate patches in five languages.
Dual plan: SDK traffic versus Studio traffic
aura-gateway separates two surfaces that have neither the same clients nor the same auth model. The data plane (port 8080, variable GATEWAY_PORT) receives SDK/app traffic, authenticated by API key (apikey, X-API-Key or ?apikey=). The management plane (port 8090, MANAGEMENT_PORT) receives Studio/admin traffic, authenticated by a JWT console (Authorization: Bearer).
Each plane carries its own stack of middleware — query identification, access log, rate limit, authentication (plane-specific), circuit breaker, then proxy — implemented in separate modules (middleware/rate_limit.rs, middleware/circuit_breaker.rs, middleware/auth_data_plane.rs, middleware/auth_management_plane.rs) rather than a single chain accidentally shared between two surfaces that should not trust each other in the same way. way.
The exact order of the middlewares, the rate limiting per target and the NATS/HTTP proxy are the subject of a dedicated article: dual-plane gateway, design a data-plane/management-plane API gateway in Rust.
Why Aurabase does not reimplement PostgREST in Rust
The self-generated REST API that the SDK consumes is not an in-house Rust module: it is the real upstream binary PostgREST (postgrest/postgrest:v12.2.8), deployed in 2 replicas per dedicated project (deploy/cnpg/tenant-postgrest.yaml), co-located with the tenant's CNPG instance. aura-provisioner creates this deployment, and aura-db probes its endpoint OPTIONS after each schema reload to confirm that PostgREST has taken the DDL change into account.
This is an assumed architectural choice, not a shortcut: PostgREST is a mature, widely adopted project, whose behavior rewriting bit by bit in Rust would bring nothing. Aurabase's Rust work is focused around — multi-tenant routing, provisioning, network isolation by NetworkPolicy, shared auth with the gateway, orchestrated schema reload — not inside the query engine itself. What this compatibility really covers, and where it stops, is the subject of a separate article: PostgREST, actual compatibility andalternatives.
Same logic on the GraphQL side: the Postgres extension pg_graphql (precompiled .deb package, v1.6.1) is installed in the dedicated CNPG image and activated on demand per project via the POST /v1/control/projects/{project_id}/graphql/enable endpoint — not a rewritten GraphQL engine either. Details and honest comparison with Hasura and PostGraphile: Native GraphQL API on Postgres with pg_graphql.
RLS and authenticator role, not an application layer
Multi-tenant isolation does not rely on an WHERE tenant_id = ? filter added by an application ORM: each request goes through the aura_authenticatorrole, which executes a SET LOCAL ROLE tenant_<uuid> transaction-scoped before executing the request — exactly the model that PostgREST itself expects. Row-Level Security does the rest, at the engine level, not at the business code level.
Not all projects share the same Postgres topology. The aura-provisioner code exposes a ProjectInstanceKind type with at least two real variants: FullyDedicated (CNPG instance entirely dedicated to the project) and SharedClusterDedicated (schema isolated by RLS on a shared CNPG cluster). The subscribed plan determines the topology — it is not a uniform promise of a “dedicated base for everyone”.
The angle “why a dedicated base per project rather than purely application isolation” is the subject of a dedicated article: RLS and dedicated base per project. The Row-Level Security documentation covers practical implementation.
NATS core, not JetStream: asynchronous messaging between services
Ten of the eleven business services declare async-nats as a direct dependency in their Cargo.toml — only aura-migrator does without it. What this crate name doesn't say: these services almost everywhere use NATS'core pub/sub API (Client::publish / publish_with_headers, at-most-once delivery without persistence or replay), not JetStream. This is the case verified in the code for the three uses that matter the most: the distribution of the PostgreSQL CDC to aura-realtime, the notification of Edge Functions jobs in aura-functions (the DLQ itself lives in Postgres, not in NATS), and provisioning events between aura-provisioner and the rest of the fleet.
JetStream — NATS' persistence and named streams mode — only appears in one verified location in the monorepo: the cross-instance presence KV Store in aura-realtime (bucket aura_presence, memory store, 60-second max_age), which synchronizes who is connected to which channel across multiple instances of ws-front — a cross-instance shared state, not a stream of events to replay. No persistent JetStream streams were found elsewhere in the workspace. The details of the CDC pipeline - wal2json, election of a unique cdc-worker by Lease Kubernetes, core NATS fan-out to the ws-frontreplicas, RLS re-verification by subscriber - are the subject of a dedicated article: broadcast the PostgreSQL CDC with NATS. The Realtime documentation covers usage on the SDK side.
Edge Functions: two runtimes for two needs
This is the most important nuance of this file, and the only real departure from pure Rust in the Aurabase product code. Each function carries a runtime field which is worth "wasm" or "deno". The invocation handler chooses the execution path accordingly — actual snippet, commented out in the code itself:
The wasm mode is native: aura-functions depends directly on Wasmtime (version 43, features async and cranelift) and executes the module in the same Rust process, with fuel counting, interruption by epoch and memory bounding via StoreLimits. The deno mode — the one used by default in the Studio editor, for almost direct Deno.serve() compatibility with existing Supabase code — delegates execution to aura-edge-runtime, a separate TypeScript service of about 550 lines, explicitly modeled — the source file header comment itself cites it — on supabase/edge-runtime (MIT license), which isolates each invocation into its own V8 Isolate.
Control — deployment, permissions, jobs, cron, quotas — remains entirely in Rust in aura-functions. Only executing user code in deno mode exits the Rust binary. This is a defensible engineering compromise (V8 Isolates are what Deno natively provides for this level of sandboxing), not an omission we prefer to keep quiet. The Wasmtime vs Wasmer comparison and the WebAssembly cold start analysis, coming soon in this file, will go further on this subject.
For the how-to doc of both deployment paths, see Edge Functions. For the Deno migration playbook from Supabase, see Migrate a Supabase project to Aurabase, which already documented this distinction before this file.
What this unified heart concretely changes for you
If you just call the API through an SDK, this architecture is invisible — that's the goal. It mainly matters to three audiences: those who evaluate the operational reliability of a multi-tenant backend before migrating production data to it, those who plan to contribute to the repository (MIT, single monorepo), and those who want to understand why a security patch on the Aurabase side spreads quickly rather than slowly.
Concretely: a single IC (cargo build --workspace, cargo test --workspace, cargo clippy --workspace --all-targets -- -D warnings) covers 90% or more of the product surface. A code review on aura-core potentially affects ten services at once — for better (a fix doesn't get lost along the way) and for worse (a poorly isolated change spreads just as quickly). It's a compromise, not a magic solution — and that's precisely why we document the actual architecture rather than a marketing summary.
The rest of the Rust Engineering file
This pillar page links to the technical analyzes of the cluster, as they are published. Actual status at time of publication of this page — links become active as soon as the corresponding article is online.
Cluster A — Framework & architecture
Axum vs Actix-web: which framework for a Rust backend in production?Published
Cargo workspace architecture: how to structure a multi-service Rust backendPublished
Dual-plane gateway: designing a data-plane/management-plane API gateway in RustPublished
Cluster B — Self-generated API on Postgres
PostgREST: what compatibility really covers, and what alternatives existPublished
Native GraphQL API on Postgres with pg_graphql: what Hasura and PostGraphile don't do the samePublished
RLS and dedicated base per project: the choice of multi-tenant insulation from AurabasePublished
Cluster C — Real time & messaging
Distribute PostgreSQL CDC with NATS: real-time architecturePublished
Cluster D — Edge Functions WebAssembly
| Wasmtime vs Wasmer: which WebAssembly runtime for Edge Functions in production | Coming soon |
|---|---|
| Edge Functions in Rust/WASM versus Cloudflare Workers and Vercel Edge | Coming soon |
| Cold start WebAssembly: what the benchmarks really say (and what we can't yet say) | Coming soon |
Cluster E — Migration & alternatives
Migrate a Supabase project to Aurabase without rewriting your RLS policiesPublished
Sovereign self-hosting: positioning Aurabase against Rust-native BaaSComing soon