Architecture¶
Spikard splits concerns between a Rust core and language-specific bindings so teams can mix runtimes without re-implementing the platform.
Layers¶
- Rust core –
crates/spikard-core(types and traits),crates/spikard-http(routing, middleware, request parsing, streaming, and error handling). - Binding crates –
crates/spikard-py,crates/spikard-node,crates/spikard-ruby,crates/spikard-php,crates/spikard-elixir– expose idiomatic APIs per language while delegating execution to the Rust runtime. - CLI –
crates/spikard-cli– entrypoint that boots the HTTP server and orchestrates code generation. - Codegen –
crates/spikard-codegen– generates DTOs/handlers and fixture-driven tests from OpenAPI/AsyncAPI contracts. Also:aleftool generates per-language bindings.
Design Principles¶
- One runtime, many languages – identical semantics for routing, validation, middleware, and streaming regardless of binding.
- Contract-first – JSON Schema and generated DTOs keep request/response shapes consistent across bindings.
- Performance with safety – Tokio/Axum base, zero-copy where possible, and strict validation before handler invocation.
- Extensibility – middleware hooks and plugin points allow cross-cutting behavior without forked frameworks.
Data Flow¶
- Inbound request hits the Rust HTTP server.
- Routing and middleware run in Rust, enriching context, enforcing auth, logging, and tracing.
- Binding bridge converts the request into the language-native representation (Python
App, TypeScriptApp, RubyApp, RustApp). - Handler execution returns a typed value that is converted back into a canonical response (JSON, streaming body, etc.).
- Validation checks schemas on both ingress and egress when configured.
See ADR 0001 for the original rationale and Python Binding Architecture for a deep dive into the PyO3 path.
High-level flow¶
graph TD
subgraph Client
A[HTTP Client]
end
subgraph RustCore["Rust Core (Axum)"]
B["Router &<br/>Handler Dispatch"]
C["Middleware Stack<br/>(Compression, Rate Limit,<br/>CORS, Auth)"]
D["Validation Engine<br/>(Schema, Constraints)"]
E["Lifecycle Hooks<br/>(Request, Pre-handler,<br/>Response, Error)"]
F["WebSocket & SSE"]
G["FFI Bridge &<br/>Handler Invocation"]
end
subgraph ErrorTypes["Error Hierarchy"]
H1["NotFound 404"]
H2["ValidationError 422"]
H3["AuthenticationError 401"]
H4["AuthorizationError 403"]
H5["RateLimitExceededError 429"]
H6["InternalError 500"]
end
subgraph Bindings["Language Bindings (14 total)"]
P["Python<br/>PyO3 + msgspec"]
N["Node/TS<br/>NAPI-RS + Zod"]
R["Ruby<br/>Magnus"]
PH["PHP<br/>ext-php-rs"]
E["Elixir<br/>Rustler"]
GO["Go<br/>cgo"]
J["Java<br/>JNI/Panama"]
CS["C#<br/>P/Invoke"]
K["Kotlin<br/>JNI"]
D["Dart<br/>FFI"]
SW["Swift<br/>C FFI"]
Z["Zig<br/>C ABI"]
CR["C<br/>C ABI"]
W["WASM<br/>Type Stubs"]
end
subgraph TestClient["Testing"]
TC["TestClient<br/>(In-process)"]
end
A --> B
B --> C
C --> D
D --> E
E --> F
F --> G
G --> H1 & H2 & H3 & H4 & H5 & H6
G --> P & N & R & PH & E & GO & J & CS & K & D & SW & Z & CR & W
TC -.-> G