ADR 0014: Service Toolbox Crate Layering¶
Status: Proposed Date: 2026-05-24
Context¶
Spikard is expanding from an HTTP framework into a broader service toolbox (see the Roadmap): storage, message brokers, a task queue and scheduler, caching, observability, and database access. These subsystems pull in heavy, system- and C-linked dependencies (object stores, broker clients, SQL drivers) and are not HTTP concerns. We need a crate layout that exposes them to all bindings without coupling the HTTP build to backends it does not use, and without bloating the WebAssembly build that already works hard to exclude non-portable code.
Three options were considered: (a) add them as modules inside crates/spikard-http;
(b) one spikard-services umbrella crate; © one dedicated crate per subsystem.
Decision¶
- Dedicated crate per subsystem:
spikard-storage,spikard-messaging,spikard-tasks,spikard-cache,spikard-db,spikard-telemetry, andspikard-cloudevents(codec and dispatch — see ADR 0023). Each owns its runtime and heavy dependencies behind its own feature flags. This mirrors the existing split (spikard-core/spikard-http/spikard-graphql/spikard-codegen) and gives independent feature gates, test suites, and versioning. - Pure-data DTOs live in
spikard-core::services: every configuration and message type (StorageConfig,BrokerConfig,ConsumerConfig,TaskQueueConfig,CronSchedule,CacheConfig,DbPoolConfig,TelemetryConfig,InboundMessage,Ack, query-result DTOs). They areSerialize/Deserializewith no backend dependencies, so alef auto-exposes them to every binding — the same mechanism that already carriesRateLimitConfig,CorsConfig, andRoute. - A new
spikard-appcrate depends onspikard-httpand the subsystem crates (feature-gated) and provides the unified application runtime (see ADR 0015). The facadecrates/spikardre-exports it. - Reject "modules in
spikard-http" (drags backend and C dependencies plus extra WebAssembly gating into every HTTP build) and the single umbrella crate (one feature namespace and one compile unit for six heavyweight dependency trees).
Consequences¶
- Subsystem configuration is shared data in
spikard-core; runtimes, clients, and callback traits stay in the subsystem crates and never cross the binding boundary as types (they arealef(skip)'d, likeHandlerandBackgroundRuntimetoday). - New
[[crates.source_crates]]entries and per-languageextra_dependenciesare added toalef.tomlfor the DTO-bearing files; WebAssembly excludes all subsystem types, as it already does forGrpcConfigandBackgroundTaskConfig. ServerConfigstays HTTP-only inspikard-http; subsystem config hangs off thespikard-appAppConfig, keeping the HTTP config and its WebAssembly exclusions stable.