Skip to Content
ArchitectureModule System

Module System

IOTA SDK’s module system enables modular, composable architecture. Each module is self-contained and can be added or removed without affecting others.

Module Lifecycle

1. Registration Phase

During application startup, each module’s Register() method is called:

Schema/migration files are typically embedded in modules; the application loads migrations from its configured migrations directory (e.g. MigrationsDir), not by modules calling a migration manager during Register().

2. Initialization Phase

Services are wired together via dependency injection:

3. Running Phase

The application serves requests with all modules active:

Module Structure

Required Files

modules/{module}/ ├── module.go # Module interface implementation └── links.go # Navigation definition

Standard Structure

modules/{module}/ ├── domain/ # Business logic │ ├── aggregates/ # Aggregate roots │ ├── entities/ # Domain entities │ └── value_objects/ # Value objects ├── infrastructure/ │ └── persistence/ # Data access │ ├── models/ # Database models │ ├── schema/ # SQL migrations │ └── *.go # Repository implementations ├── services/ # Business services ├── presentation/ │ ├── controllers/ # HTTP handlers │ └── templates/ # Templ files ├── module.go # Module registration └── links.go # Navigation

Module Interface

All modules implement the application.Module interface:

Registration Methods

MethodPurposeCalled In
RegisterServices()Add business servicesServices layer
RegisterControllers()Add HTTP handlersPresentation layer
RegisterMiddleware()Add request middlewareInfrastructure
RegisterLocaleFiles()TranslationsPresentation
RegisterHashFsAssets()Static assetsPresentation
QuickLinks().Add(spotlight.NewQuickLink(trKey, link)...)Spotlight quick linksNavigation / actions

Service Registration

Service Pattern

Services are registered as interfaces and retrieved by type:

Dependency Injection

Services declare dependencies explicitly:

Controller Registration

Routing

Controllers define their base path during registration:

Permission Integration

Controllers check permissions via middleware:

Cross-Module Communication

Service Access

Modules access other modules via the service registry:

Event-Driven Communication

Loose coupling via domain events:

Module Configuration

Module Options

Modules accept configuration via options pattern:

Environment-Based Config

Configuration can vary by environment:

EnvironmentConfigurationPurpose
DevelopmentDebug logging, test endpointsDevelopment
StagingProduction-like, limited dataTesting
ProductionOptimized, no debug infoProduction

Best Practices

  1. Single Responsibility - Each module handles one business domain
  2. Explicit Dependencies - Declare all required services
  3. No Circular Dependencies - Module A shouldn’t depend on B if B depends on A
  4. Event-Based Coupling - Use events for loose coupling
  5. Interface Segregation - Small, focused service interfaces

Built-in Modules

Modules are loaded from modules.BuiltInModules (see modules/load.go): core, hrm, finance, projects, logging, warehouse, crm, website, billing, oidc, testkit. BiChat and Superadmin are not in BuiltInModules (BiChat is conditionally loaded when configured; Superadmin is a separate cmd/superadmin application).

Next Steps

Last updated on