Skip to main content

10. NestJS Modular Architecture

Status: Accepted Date: 2025-07-06

Context

The Arcana Backend is a complex application with several distinct domains: Telegram bot interaction, tarot reading logic, AI interpretations, data persistence, and a REST API. Without a clear architectural pattern, the codebase could become tightly coupled and difficult to maintain or extend.

Decision

We decided to adopt a modular architecture using the NestJS framework. Each core feature (e.g., deck, reading, telegram, ai) is encapsulated within its own NestJS module. This promotes a clear separation of concerns, where each module has a distinct responsibility and a well-defined public API for interacting with other modules.

Consequences

Positive:

  • Improved maintainability and scalability. New features can be added as new modules with minimal impact on existing code.
  • Enhanced team collaboration, as different developers can work on separate modules concurrently.
  • Clear boundaries enforce a clean architecture, preventing business logic from leaking into transport layers (like API controllers or Telegram handlers).
  • NestJS's dependency injection system simplifies testing and mocking.

Negative:

  • Can introduce some boilerplate code for module definitions.
  • Requires a deeper understanding of NestJS conventions and module system for new developers.
  • Care must be taken to define clear contracts between modules to avoid creating implicit, tight coupling.

Mitigation:

  • Boilerplate: Develop internal schematics or code generation tools to automate the creation of new modules and their associated files.
  • Learning Curve: Maintain clear documentation on our architectural patterns and provide onboarding sessions for new developers on NestJS and our module structure.
  • Coupling: Enforce strict module boundaries using tools like depcheck or custom linting rules. Conduct regular architecture reviews to identify and refactor any emerging coupling issues.