Skip to content

Architecture

Spikard splits concerns between a Rust core and language-specific bindings so teams can mix runtimes without re-implementing the platform.

Layers

  • Rust corecrates/spikard-core (types and traits), crates/spikard-http (routing, middleware, request parsing, streaming, and error handling).
  • Binding cratescrates/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.
  • CLIcrates/spikard-cli – entrypoint that boots the HTTP server and orchestrates code generation.
  • Codegencrates/spikard-codegen – generates DTOs/handlers and fixture-driven tests from OpenAPI/AsyncAPI contracts. Also: alef tool 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

  1. Inbound request hits the Rust HTTP server.
  2. Routing and middleware run in Rust, enriching context, enforcing auth, logging, and tracing.
  3. Binding bridge converts the request into the language-native representation (Python App, TypeScript App, Ruby App, Rust App).
  4. Handler execution returns a typed value that is converted back into a canonical response (JSON, streaming body, etc.).
  5. 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 &amp;<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 &amp; SSE"]
    G["FFI Bridge &amp;<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 &amp; H2 &amp; H3 &amp; H4 &amp; H5 &amp; H6
  G --> P &amp; N &amp; R &amp; PH &amp; E &amp; GO &amp; J &amp; CS &amp; K &amp; D &amp; SW &amp; Z &amp; CR &amp; W
  TC -.-> G

Edit this page on GitHub