Carrier
Architecture · 1.3.4

.carrier → lexer → parser → AST → semantic → IR → rust | java | node.

Carrier keeps a real compiler pipeline. Lex / parse / semantic / IR are shared; the codegen step splits into three peers — a Rust + Cargo binary for production, a Spring Boot service for JVM-native shops, and a Node + Fastify target for sub-second dev iteration. Same migration SQL across all three, byte-identical. 1.3.4 carries a written stability policy, a 1.x upgrade guarantee, remote SSH builds, and first-class deploy targets — Carrier Cloud, Compose, Kubernetes, edge WASM.

Pipeline

Stages and responsibilities

01
.carrier
source
02
lexer
tokens
03
parser
AST
04
semantic
types · validation
05
IR
lowering
06
codegen
rust
07
cargo / rustc
build
08
service
native binary
crates/carrier-*.carrier/build/<binary>
Crates

Ten crates. One job each. Three codegen targets.

The compiler workspace is a plain Cargo workspace. Reading the code is the fastest way to understand how Carrier behaves.

carrier-lexerTokenizer

Converts .carrier source into tokens with spans. Handles comments, doc comments, string literals, identifiers, and attribute annotations.

carrier-parserParser

Produces the AST for declarations, statements, and expressions. Preserves spans for diagnostic-quality error messages.

carrier-astAST nodes

Span-carrying syntax tree. The canonical shape every later stage consumes.

carrier-semanticSemantic analysis

Name resolution, type checking, CRUD and auth validation, policy checks, idempotency scope rules, workflow dependency graphs, LLM tool schema inference, role hierarchy resolution, invariant + SLA validation, built-in call signatures.

carrier-irIntermediate form

Lowers the semantic model into a codegen-oriented program. Decouples language surface from generation. Both Rust and Node targets read the same IR.

carrier-codegen-rustRust target

Generates a standalone Rust service project plus OpenAPI, manifest, migration artifacts, and OTLP telemetry wiring. Tokio + Axum + sqlx. Shards generated source under .carrier/generated/src/generated/ for stable file boundaries.

carrier-codegen-javaJava / Spring Boot target

Generates a Spring Boot 3.x service for JVM-native deployments. Java 21 source + Maven, JDBC + HikariCP, Spring Security for the JWT auth surface. Same migration SQL as the Rust target, byte-identical.

carrier-codegen-nodeNode target

Generates a Fastify + pg dev project for fast iteration (~200ms restart). Same migration SQL as the other targets, byte-identical. Bails clearly on shapes that need significant runtime scaffolding.

carrier-runtimeRuntime helpers

The internal runtime: auth + JWT rotation + JWKS, Postgres pooling, cache, jobs, schedules, events, workflows, queues, realtime transports, LLM dispatch, idempotency advisory locks, outbound HTTP, runtime depth guards, panic capture, evidence bundles, Carrier Flight Recorder.

carriercCompiler CLI

Project discovery, generation, build orchestration (local + remote SSH), dev watch, tests, evals, invariant verification, harden, tune, manifest audit, OpenAPI export, migrations, deploy compose / k8s / edge, remote (Carrier Cloud), agent docs, React Native SDK generator.

Runtime

What the generated service gets for free.

Generated Rust services link against carrier-runtime. You never write against it directly — it powers the constructs you declare in .carrier source.

Async server
Tokio async runtime. Axum routing. Request body size limits. Graceful shutdown.
Standard endpoints
/health · /ready · /openapi.json · /docs.
Auth
JWT issue/verify, HS256-pinned verification, secret rotation via JWT_SECRET_PREVIOUS, clock-skew leeway, auth.current_user.
Postgres
Connection pooling, bootstrap database creation, generated migration application, pgvector column DDL + HNSW/IVFFlat indexes.
Policy session context
Sets carrier.current_roles, carrier.current_tenant, and carrier.current_user per request. Cleared on pooled connection reuse (tested).
Idempotency
Persistent response replay with Postgres advisory locks serializing concurrent first-writers. Caller-aware scope: {METHOD} {PATH}:user:{id}:tenant:{t}:workspace:{w}.
Cache
Redis when REDIS_URL is healthy, otherwise an in-memory fallback. Keys are tenant-scoped by the runtime.
Workflows
Durable linear/saga/graph workflows. Per-step retry overrides, typed compensation, parallel branches, durable leases, operator retry_compensation.
Queues
Redis-backed typed queues, consumers bound to Carrier jobs, configurable concurrency, ack modes, retry backoff, and dead-letter routing.
Realtime streams
WS → SSE → long-poll transport negotiation, tenant/workspace/group scoping, post-commit fanout for watch emissions.
LLM runtime
Typed tool dispatch reapplies auth + policy context, persists transcripts, audits every tool call, emits realtime chunk/tool events per client.
Telemetry (OTLP)
Opt-in OpenTelemetry export (OTLP HTTP or gRPC) for traces, metrics, and logs. Zero-boilerplate spans on every execution boundary.
Outbound HTTP
JSON HTTP helpers backing client declarations. Spans annotated with carrier.client_name.
Stability policy

1.3.4 is the release candidate. 1.0 is a promise, not a rewrite.

Stable surfaces are anchored by fixture-based manifest/OpenAPI drift tests in CI, a written deprecation window, and a documented 1.x upgrade path.

Stable at 1.3.4
  • Language grammar and currently implemented declarations
  • fail(code, message) body shape (code · message · request_id · details?)
  • Runtime-reserved error codes (unauthorized, forbidden, conflict, validation_failed, …)
  • carrier.toml format + .carrier/ artifact layout
  • CurrentUser shape (id, email, name, roles, tenant_id?, workspace_id?)
  • System-table names and column contracts (see below)
  • OpenAPI extensions: x-carrier-ai-hint, x-carrier-idempotent, x-carrier-cache, x-carrier-telemetry, x-carrier-workflows
  • CLI commands and documented flags
  • Stable OTLP attribute names (carrier.*)
Experimental at 1.3.4
  • Generated Rust source layout under .carrier/generated/src/
  • Vendored runtime implementation under .carrier/generated/vendor/
  • llm client declaration grammar and built-in call surface
  • Manifest llm_clients section and x-carrier-llm-clients OpenAPI extension
  • Benchmark harness internals
  • Test-only helper APIs for test blocks
  • Startup banner text outside documented JSON fields
Deprecation window
No silent removal in patch releases. Minimum 90-day notice. Stable features must be available for at least one later minor release before removal.
1.x upgrade guarantee
Upgrade compiler → carrier check carrier migrate generate carrier migrate up. No hand-edits to source or checked-in migrations.
Not promised
Crate split under crates/, generated Rust internals, undocumented env vars, undocumented benchmark numbers.
System tables

Durable operational state, in Postgres

Every Carrier service owns a small set of carrier_* tables. Their column contracts are part of the 0.9 stability policy.

carrier_idempotency_keys

route_scope · idempotency_key · response_body · replay_count · last_replayed_at

carrier_jobs

job_name · payload · current_user · trace_context · status · attempts · available_at · last_error

carrier_events

sequence · event_name · payload · current_user · trace_context

carrier_event_deliveries

event_id · subscriber · attempts · delivered_at · last_error

carrier_audit_log

action · entity · entity_id · metadata · before_value · after_value · current_user

carrier_schedule_runs

schedule_name · scheduled_for · created_at

carrier_workflow_state

workflow_name · input_payload · step_results · output_payload · status · attempts · lease_expires_at · timeout_at

carrier_workflow_tasks

run_id · step_name · status · attempts · available_at · lease_expires_at · last_error

carrier_llm_conversations

client_name · provider · wire_format · model · status · tokens · current_user

carrier_llm_messages

conversation_id · sequence · role · message · input_tokens · output_tokens

Deploy targets

One source tree. Carrier Cloud, Compose, Kubernetes, edge WASM.

The same compiler artifacts feed Carrier Cloud's HTTPS bundle path, generated docker-compose stacks, multi-region Kubernetes manifests, and Cloudflare/Fastly edge adapters.

Carrier Cloud
carrier remote login → deploy → status / logs / open. Reproducible HTTPS upload bundle, sorted by relative path, with --wait for terminal state.
Compose
carrier deploy compose generates a Compose file + Dockerfile from the compiled project plus .env.example defaults.
Kubernetes
carrier deploy k8s emits ConfigMap, Secret, Deployment, Service, HPA, and PDB. --multi-region emits one api/worker pair per declared tenant residency region.
Edge WASM
carrier deploy edge --target cloudflare | fastly requires deploy { routes: edge_wasm }; outputs route manifests + adapter files.
MCP servers
The compiled service binary speaks MCP over stdio: .carrier/build/<svc> mcp. Actions become synchronous tools; workflow tools enqueue runs and return run_id.
Compliance
carrier compliance generate --standard hipaa | ferpa | pci-dss | soc2 writes evidence backed by Carrier metadata + observed audit data. Hash-chain verification via verify-audit-chain.
Workflow promote
carrier workflow promote <id> snapshots a runtime-authored workflow into a managed bundle: scaffold_only or behaviorally_complete.
Artifacts

Every build emits the same shape

Deterministic, machine-readable outputs — not debug artifacts. Tools can treat these as the ground truth of a Carrier project.

.carrier/
  • .carrier/generated/generated Rust service project
  • .carrier/generated/migrations/SQL migrations & schema snapshots
  • .carrier/manifest.jsondeclarations · routes · models · policies · jobs
  • .carrier/build/<binary>native executable
At runtime
  • /openapi.jsonserved by the binary
  • /docsAPI explorer UI
  • /health · /readyliveness · readiness
  • JSON logs to stdoutstructured metadata for downstream collectors
Data access ladder

Escape hatches are intentional, not afterthoughts

Carrier defines a clear sequence for how you reach for Postgres. Most code lives at the top. Escape hatches are explicit and typed.

  1. 1
    Generated CRUD
    standard list · get · create · update · delete · restore
  2. 2
    Model helpers
    Model.get, Model.search, count_by_*, exists_by_*, get_by_*, list_by_*
  3. 3
    Vector helpers
    Model.similar_with_scores(...), Model.hybrid_search(...) when Vector(N) + searchable
  4. 4
    Actions + transactions
    auth context, row locks via get_for_update, cache, jobs, audit
  5. 5
    Raw SQL
    sql.list_as, sql.one_as, sql.scalar_as, sql.exec — typed results
  6. 6
    DB functions
    db.call_as, db.fn_one_as, db.fn_scalar_as — stored functions & builtins
Honest

Current limits

Carrier ships what the compiler actually implements. These are the places where it deliberately stops short today.

Imports
Validated metadata. Every file under src/ still compiles together — imports are not yet selective loaders.
Migration diffing
Structural. Renames are not inferred automatically. Migrations are explicit SQL artifacts under .carrier/generated/migrations/.
Scheduled payloads
Scheduled jobs currently enqueue the target job with an empty JSON object payload. Use Json payload types so the job body handles an empty input.
transaction + return
return from inside a transaction { } block is not supported yet. Do work in the block; return after.
Telemetry
JSON logs, events, audit records, and job/schedule state are durable. Native Sentry, OpenTelemetry, Datadog, or ELK integrations are intentionally not built in.
Generated Rust
Generated Rust can still produce warnings in some app shapes. The service builds and runs; lint cleanliness is progressive.