# ADR-0021: Module Loading Strategy ## Status Accepted ## Context The platform needs to support pluggable modules. Two approaches: 1. **Static registration** - Modules compiled into binary 2. **Dynamic plugin loading** - Load `.so` files at runtime Each has trade-offs for development, CI, and production. ## Decision Support **both approaches** with **static registration as primary**: 1. **Static registration (primary)**: - Modules register via `init()` function - Imported via `import _ "module/pkg"` in main - Works everywhere (Windows, Linux, macOS) - Compile-time type safety 2. **Dynamic plugin loading (optional)**: - Support via Go `plugin` package - Load `.so` files from `./plugins/` directory - Only for production scenarios requiring hot-swap - Linux/macOS only (Go plugin limitation) **Rationale:** - Static registration is simpler and more reliable - Works in CI/CD (no plugin compilation needed) - Compile-time safety catches errors early - Dynamic loading provides flexibility for specific use cases - Modules can choose their approach ## Consequences ### Positive - Flexible: static for most cases, dynamic when needed - Static registration works everywhere - Compile-time safety with static - Hot-swap capability with dynamic (Linux/macOS) ### Negative - Two code paths to maintain - Dynamic plugins have version compatibility constraints - Plugin debugging is harder ### Implementation Notes - Implement static registry in `internal/registry/registry.go` - Modules register via: `registry.Register(Module)` in `init()` - Implement plugin loader in `internal/pluginloader/plugin_loader.go` (optional) - Document when to use each approach - Validate plugin version compatibility if using dynamic loading