CatalyzeUp
sondely/technical

System Architecture

Overview

Sondely follows a modern, scalable architecture optimized for high concurrency, rapid development, and comprehensive testing.

This page describes the Python app that serves sondely.com today. Its replacement, one Next.js app on Postgres with the Sona assistant, was built on 7 and 8 November 2026 and is described in Moving Sondely to the TourCockpit Platform.

Architecture Principles

  1. Backend-First Development: Business logic in API layer
  2. Massive Parallelization: Support 1000+ concurrent operations
  3. In-Memory for Development: Zero disk I/O during development
  4. Test Everything: 100% backend coverage, E2E for critical paths
  5. Clean Separation: Clear boundaries between layers

System Components

Backend (FastAPI + MongoDB)

Frontend (React + Vite)

Technology Stack

Backend Technologies

  • Framework: FastAPI (async Python)
  • Database: MongoDB with Motor (async driver)
  • Cache: Redis for sessions and temporary data
  • Auth: JWT with refresh tokens
  • Validation: Pydantic models
  • Testing: pytest with pytest-asyncio
  • Background work: an asyncio reminder loop started inside each replica (services/reminder_engine.py)
  • Email: Azure Communication Services

Frontend Technologies

  • Framework: React 19
  • Build Tool: Vite
  • Language: TypeScript
  • Styling: Tailwind CSS
  • State: React Query + Context
  • Forms: React Hook Form
  • Charts: Recharts/D3.js
  • Testing: Vitest + React Testing Library

Infrastructure

  • Container: Docker + Docker Compose
  • CI/CD: GitHub Actions
  • Monitoring: OpenTelemetry
  • Logging: Structured JSON logs
  • Deployment: Azure Container Apps (impactpulse, impactpulse-prod)

Data Flow

Request Flow

Authentication Flow

Session Management

Database Design

MongoDB Advantages

  • Flexible schema for survey responses
  • Native JSON storage
  • Horizontal scaling capability
  • Aggregation pipeline for analytics
  • Change streams for real-time updates

Collection Relationships

API Design

RESTful Principles

  • Resource-based URLs
  • HTTP verbs for actions
  • Consistent response format
  • HATEOAS where applicable

Response Format

{
  "success": true,
  "data": {},
  "message": "Operation successful",
  "errors": [],
  "metadata": {
    "timestamp": "2024-01-15T10:00:00Z",
    "request_id": "uuid"
  }
}

Error Handling

{
  "success": false,
  "data": null,
  "message": "Validation failed",
  "errors": [
    {
      "field": "email",
      "message": "Invalid email format"
    }
  ]
}

Security Architecture

Authentication

  • JWT tokens with short expiry (15 min)
  • Refresh tokens with longer expiry (7 days)
  • Organization context in token claims
  • Role-based access control (RBAC)

Authorization

# Decorator-based authorization
@require_auth
@require_role("admin")
@require_organization
async def admin_endpoint():
    pass

Data Security

  • Encryption at rest (MongoDB)
  • TLS for all connections
  • Input validation and sanitization
  • XSS protection
  • CSRF tokens

Scalability Patterns

Horizontal Scaling

  • Stateless API servers
  • MongoDB replica sets
  • Redis cluster
  • Load balancer distribution

Caching Strategy

  • Redis for session data
  • MongoDB query result caching
  • Frontend API response caching
  • CDN for static assets

Performance Optimizations

  • Database indexing
  • Query optimization
  • Lazy loading
  • Pagination
  • Request batching

Background Jobs

Job Types

  • Email reminders
  • Report generation
  • Data aggregation
  • Cleanup tasks

Job Architecture

There is no job queue. The reminder loop runs every 60 seconds inside every replica of the API, started at application startup (main.py), so with several replicas several loops run at once; the new platform replaces it with one scheduled job (Infrastructure and Deploy).

Testing Architecture

Testing Levels

  1. Unit Tests (80%): Business logic
  2. Integration Tests (15%): API endpoints
  3. E2E Tests (5%): Critical user flows

Testing Strategy

# Parallel execution
pytest -n 32

# Test isolation
@pytest.fixture
async def test_db():
    # Create test database
    # Run migrations
    # Yield
    # Cleanup

Monitoring & Observability

Metrics

  • Request latency
  • Error rates
  • Database performance
  • Queue depth
  • Email delivery rates

Logging

logger.info("Survey completed", extra={
    "user_id": user_id,
    "survey_id": survey_id,
    "attempt": attempt_number,
    "duration": duration
})

Tracing

  • OpenTelemetry integration
  • Distributed tracing
  • Performance profiling

Development Environment

Local Setup

# Backend
docker-compose up mongodb redis
cd backend && uvicorn app.main:app --reload

# Frontend
cd frontend && npm run dev

# Tests
pytest tests/ -n auto

Environment Variables

# Development
USE_INMEMORY_DB=true
DEBUG=true
LOG_LEVEL=debug

# Production
USE_INMEMORY_DB=false
DEBUG=false
LOG_LEVEL=info

Deployment Architecture

Container Strategy

# Multi-stage build
FROM python:3.11 as builder
# Build dependencies

FROM python:3.11-slim
# Copy only necessary files
# Run application

Zero-Downtime Deployment

  1. Build new container
  2. Run migrations
  3. Health check
  4. Switch load balancer
  5. Drain old containers

Future Considerations

Microservices (if needed)

  • Auth service
  • Email service
  • Analytics service
  • Survey service

Event-Driven Architecture

  • Event sourcing for audit trail
  • CQRS for read/write separation
  • Message queue for async operations

Multi-Region

  • Geographic distribution
  • Data residency compliance
  • Edge caching