Skip to main content

High-Level Architecture

The LTV.ai backend follows a modular monolith architecture built on NestJS. Each domain area is encapsulated in its own module with clear boundaries.
┌─────────────────────────────────────────────────────┐
│                   API Gateway Layer                   │
│         REST Controllers + GraphQL Resolvers          │
├──────────┬──────────┬──────────┬────────────────────┤
│Reactivate│  Ecomm   │  Billing │    Public API       │
│ Module   │  Stores  │  Module  │    (GraphQL)        │
├──────────┴──────────┴──────────┴────────────────────┤
│                  Core Services                        │
│      Auth │ Reporting │ Admin │ Customer             │
├─────────────────────────────────────────────────────┤
│              Infrastructure Layer                      │
│  TypeORM │ Redis │ Elasticsearch │ SQS │ S3 │ KMS    │
├──────────┬──────────┬──────────┬────────────────────┤
│PostgreSQL│ClickHouse│  Redis   │  AWS Services       │
└──────────┴──────────┴──────────┴────────────────────┘

Module Architecture

Reactivate Module

The email automation and AI marketing engine. Manages email sequences, campaign generation, customer segmentation, scheduling, and AI-powered content creation. Contains 23 controllers.

Ecommerce Stores Module

Adapters for Shopify and BigCommerce. Handles OAuth flows, webhook processing, order/customer sync, product catalog updates, and platform-specific SSO.

Billing Module

Manages merchant subscription billing, payment processing, and invoice generation.

Public API Module

GraphQL resolvers for customer-facing operations: authentication, OTP verification, and billing management.

Design Patterns

Use Case Pattern

Business logic is encapsulated in Use Case classes following clean architecture principles. Each use case represents a single business operation.
// Example: UserRegistersWithPasswordUseCase
@Injectable()
export class UserRegistersWithPasswordUseCase {
  constructor(
    private readonly userRepository: UserRepository,
    private readonly passwordService: PasswordService,
  ) {}

  async execute(dto: RegisterUserDto): Promise<User> {
    // Business logic here
  }
}

Guard-Based Authorization

Authentication and authorization use NestJS guards that validate JWTs and API keys before requests reach controllers.
Request → Guard → Interceptor → Controller → Use Case → Repository

Event-Driven Processing

Asynchronous operations use AWS SQS queues and NestJS event emitters for decoupled processing of:
  • Email delivery and scheduling
  • Webhook event processing
  • Catalog updates
  • Customer segmentation
  • Profile sync operations

Data Flow

Email Sequence Flow

Marketing Analyst → Generate Segments
    → Create Sequence → Generate Email Copy (AI)
    → Schedule via SQS → Batch Send (SendGrid)
    → Track Events → Update Metrics (ClickHouse)

Ecommerce Data Sync Flow

Ecommerce Webhook → Webhook Controller → Sync Use Case
    → Update Customer Data
    → Sync Product Catalog
    → Feed Segmentation Engine

Database Architecture

DatabasePurposeKey Data
PostgreSQLTransactional dataCustomers, retailers, emails, sequences
ClickHouseAnalyticsEmail metrics, conversion rates, aggregated reports
RedisCaching & sessionsJWT sessions, rate limiting, report caching, throttling
ElasticsearchSearchCustomer profiles, full-text search