Skip to main content

System Architecture

FlexPrice uses a modern, scalable microservices architecture designed to handle high-volume usage metering and real-time billing calculations. FlexPrice Architecture

Technology Stack

FlexPrice is built on proven, production-ready technologies:

Go 1.23+

High-performance backend written in Go for speed and reliability

Gin Framework

Fast HTTP web framework with middleware support

PostgreSQL

Transactional database for core business data

ClickHouse

Analytics database for high-volume event storage

Apache Kafka

Message queue for reliable event processing

Temporal

Workflow engine for long-running billing processes

Ent ORM

Entity framework for type-safe database operations

Uber FX

Dependency injection framework for clean architecture

Core Services

FlexPrice runs three main service types that can be deployed independently for scalability:
Deployment Mode: apiThe API service handles all HTTP requests:
  • Usage event ingestion
  • Customer and plan management
  • Invoice generation requests
  • Feature entitlement checks
  • Real-time usage queries
Configuration:
export FLEXPRICE_DEPLOYMENT_MODE=api
Docker Compose:
flexprice-api:
  image: flexprice-app:local
  ports:
    - "127.0.0.1:8080:8080"
  environment:
    - FLEXPRICE_DEPLOYMENT_MODE=api
    - FLEXPRICE_POSTGRES_HOST=postgres
    - FLEXPRICE_KAFKA_BROKERS=kafka:9092
    - FLEXPRICE_CLICKHOUSE_ADDRESS=clickhouse:9000
    - FLEXPRICE_TEMPORAL_ADDRESS=temporal:7233

Infrastructure Components

PostgreSQL

Stores transactional data with strong consistency guarantees:
  • Customers, plans, subscriptions
  • Pricing rules and configurations
  • Invoices and payment records
  • Credit grants and wallet balances
  • Feature definitions and entitlements
Connection Details (Local):
Host: localhost
Port: 5432
Database: flexprice
Username: flexprice
Password: flexprice123

ClickHouse

Handles high-volume analytics and event storage:
  • Raw usage events (millions per second)
  • Aggregated usage metrics
  • Time-series analysis
  • Cost calculations
  • Audit logs
Connection Details (Local):
Host: localhost
HTTP Port: 8123
Native Port: 9000
Database: flexprice
Username: flexprice
Password: flexprice123

Apache Kafka

Provides reliable, ordered event streaming: Topics:
  • events - Raw event ingestion from API
  • events_lazy - Deferred event processing
  • events_post_processing - Post-processing pipeline
  • system_events - Internal system events and webhooks
Connection Details (Local):
Bootstrap Server: localhost:29092
Internal Address: kafka:9092
Kafka UI is available at http://localhost:8084 with the --profile dev flag.

Temporal

Orchestrates long-running business processes:
  • Workflows: Multi-step billing processes
  • Activities: Individual tasks (invoice generation, payment processing)
  • Retry Logic: Automatic retry with exponential backoff
  • Observability: Full execution history and debugging
Connection Details (Local):
Temporal Server: localhost:7233
Temporal UI: http://localhost:8088

Layered Architecture

FlexPrice follows clean architecture principles with clear separation of concerns:
1

Domain Layer

Location: internal/domain/Core business entities and domain models:
  • Pure business logic
  • Repository interfaces (no implementations)
  • No external dependencies
  • Framework-agnostic
// Example: Domain interface
type EventRepository interface {
    Create(context.Context, *Event) error
    FindByID(context.Context, string) (*Event, error)
}
2

Repository Layer

Location: internal/repository/Data access implementations:
  • Implements domain repository interfaces
  • Direct database access (Ent, ClickHouse)
  • Data mapping and persistence
  • Query optimization
// Example: Repository implementation
type clickhouseEventRepository struct {
    client *clickhouse.Client
}

func (r *clickhouseEventRepository) Create(ctx context.Context, event *Event) error {
    // ClickHouse insertion logic
}
3

Service Layer

Location: internal/service/Business logic orchestration:
  • Uses repository interfaces
  • Transaction management
  • Complex business rules
  • Temporal workflow integration
// Example: Service composition
type BillingService struct {
    eventRepo    domain.EventRepository
    invoiceRepo  domain.InvoiceRepository
    temporal     TemporalService
}
4

API Layer

Location: internal/api/HTTP request/response handling:
  • Request validation
  • DTO conversions
  • Response formatting
  • No business logic
// Example: API handler
func (h *EventHandler) Create(c *gin.Context) {
    var req CreateEventRequest
    if err := c.ShouldBindJSON(&req); err != nil {
        c.JSON(400, gin.H{"error": err.Error()})
        return
    }
    // Delegate to service layer
    event, err := h.service.CreateEvent(c.Request.Context(), req)
}

Event Processing Flow

Understand how usage events flow through the system:
1

Event Ingestion

Events arrive via API or SDK:
POST /v1/events
{
  "customer_id": "customer_123",
  "event_name": "api_call",
  "timestamp": "2026-03-03T10:30:00Z",
  "properties": {
    "endpoint": "/api/users",
    "method": "GET"
  }
}
2

Kafka Publishing

API service publishes event to Kafka events topic for reliable processing
3

Consumer Processing

Consumer service:
  • Reads events from Kafka
  • Validates event structure
  • Enriches with customer/plan data
  • Writes to ClickHouse
4

Metering & Analytics

  • Real-time aggregation of usage metrics
  • Feature usage tracking and limits
  • Cost calculation based on pricing rules
  • Alert triggers for thresholds
5

Billing Workflows

Temporal workflows triggered for:
  • Invoice generation at billing cycle end
  • Credit deductions
  • Overage calculations
  • Payment processing

Project Structure

flexprice/
├── cmd/
│   ├── server/          # Main application entry point
│   └── migrate/         # Database migration tool
├── ent/
│   └── schema/          # Ent entity schemas (data models)
├── internal/
│   ├── api/             # HTTP handlers and routing
│   │   ├── v1/          # API v1 handlers
│   │   └── cron/        # Scheduled job handlers
│   ├── domain/          # Domain models and interfaces
│   ├── repository/      # Data access layer implementations
│   ├── service/         # Business logic layer
│   ├── temporal/        # Temporal workflows and activities
│   │   ├── workflows/   # Workflow definitions
│   │   └── activities/  # Activity implementations
│   ├── integration/     # Third-party integrations
│   ├── config/          # Configuration management
│   ├── postgres/        # PostgreSQL client
│   ├── clickhouse/      # ClickHouse client
│   └── kafka/           # Kafka producer/consumer
├── migrations/
│   ├── postgres/        # PostgreSQL migrations
│   └── clickhouse/      # ClickHouse migrations
└── api/                 # Generated SDKs
    ├── go/              # Go SDK
    ├── python/          # Python SDK
    ├── typescript/      # TypeScript SDK
    └── mcp/             # MCP server

Dependency Injection

FlexPrice uses Uber FX for dependency injection:
func main() {
    app := fx.New(
        // Infrastructure
        fx.Provide(postgres.NewClient),
        fx.Provide(clickhouse.NewClient),
        fx.Provide(kafka.NewProducer),
        fx.Provide(temporal.NewClient),
        
        // Repositories
        fx.Provide(repository.NewEventRepository),
        fx.Provide(repository.NewInvoiceRepository),
        
        // Services
        fx.Provide(service.NewBillingService),
        fx.Provide(service.NewMeteringService),
        
        // API
        fx.Provide(api.NewRouter),
        
        // Lifecycle
        fx.Invoke(startServer),
    )
    
    app.Run()
}

Multi-Tenancy Model

All data is isolated by tenant and environment:
Top-level isolation boundary representing a company or organization.Each tenant has:
  • Separate API keys
  • Independent data storage
  • Isolated billing cycles
  • Dedicated configurations
All database queries and API operations are automatically scoped to tenant + environment for data isolation.

Scalability & Performance

Horizontal Scaling

Scale each service independently:
  • Multiple API instances behind load balancer
  • Consumer instances with Kafka consumer groups
  • Worker instances for parallel workflow execution

High Throughput

Handle millions of events per second:
  • Kafka buffering and batching
  • ClickHouse columnar storage
  • Async event processing

Real-Time Processing

Low-latency event to insight:
  • Sub-second event ingestion
  • Real-time usage aggregation
  • Immediate feature limit checks

Reliability

Built-in resilience:
  • Temporal automatic retries
  • Kafka message persistence
  • Database transaction safety

Integrations

FlexPrice integrates with your existing tools: Payment Providers:
  • Stripe
  • Chargebee
  • Razorpay
CRM Systems:
  • HubSpot
  • Salesforce (via API)
Accounting:
  • QuickBooks
  • NetSuite (via API)
Integration implementations are in internal/integration/ using a factory pattern for provider instantiation.

Configuration Management

Configuration is managed via Viper with multiple sources:
1

Config File

Default configuration in internal/config/config.yaml
2

Environment Variables

Override with environment variables (prefix: FLEXPRICE_)Examples:
  • FLEXPRICE_POSTGRES_HOST overrides postgres.host
  • FLEXPRICE_KAFKA_BROKERS overrides kafka.brokers
3

.env File

Loaded automatically by godotenv for local development

Monitoring & Observability

Structured Logging

JSON logs via internal/logger for easy parsing and analysis

Temporal UI

Complete workflow execution history, debugging, and manual triggers at http://localhost:8088

Kafka UI

Monitor topics, messages, and consumer lag at http://localhost:8084

Health Checks

Service health endpoints for load balancer integration

Security

API Key Authentication

All API requests require valid API key in X-API-Key header

Tenant Isolation

Automatic data scoping prevents cross-tenant data access

Database Security

Encrypted connections, credential management, prepared statements

Audit Logging

All operations logged with user context for compliance

Next Steps

API Reference

Explore all available endpoints and data models

Product Catalog

Set up plans, pricing, and features

Event Ingestion

Learn about event schemas and best practices

Contributing

Contribute to FlexPrice development