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
- Backend-First Development: Business logic in API layer
- Massive Parallelization: Support 1000+ concurrent operations
- In-Memory for Development: Zero disk I/O during development
- Test Everything: 100% backend coverage, E2E for critical paths
- 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
- Unit Tests (80%): Business logic
- Integration Tests (15%): API endpoints
- 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
- Build new container
- Run migrations
- Health check
- Switch load balancer
- 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