Overview
Architecture Decision Records (ADRs) capture important architectural decisions made during the development of the Learnille platform. Each ADR describes the context, decision, and consequences of a significant architectural choice.ADR Template
ADR [Number]: [Title]
Date: YYYY-MM-DD Status: [Proposed | Accepted | Rejected | Deprecated | Superseded] Context: [Describe the context and problem being solved] Decision: [Describe the decision that was made] Consequences: [Describe the positive and negative consequences of the decision] Alternatives Considered: [List alternative solutions that were considered] Related ADRs: [Links to related ADRs]Current ADRs
ADR 001: Technology Stack Selection
Date: 2024-01-15 Status: Accepted Context: We needed to choose a technology stack for building the Learnille platform that would support rapid development, scalability, and maintainability. The platform requires handling user authentication, course management, payments, and real-time features. Decision: We decided to use:- Frontend: React with TypeScript (Vite)
- Backend: Node.js with NestJS framework
- Database: PostgreSQL (Self-Hosted)
- Cache & Queue: Redis / BullMQ
- Search: OpenSearch for vector and course search
- Storage: Cloudflare R2 (S3 API compatible) / MinIO locally
- Hosting & Observability: Self-Hosted Infrastructure with New Relic APM/Logs & Sentry
-
Positive:
- Strong TypeScript support improves code quality and developer experience
- NestJS provides excellent structure and scalability
- PostgreSQL offers robust relational data management
- Cloudflare R2 eliminates egress bandwidth costs
- Self-hosting provides operational autonomy and predictable costs
- New Relic provides centralized APM and log aggregation
-
Negative:
- Self-hosting requires maintaining server deployment scripts and backups
- Team operational responsibility for infrastructure health
- Python/Django: More mature but slower development
- Ruby on Rails: Rapid development but less scalable
- Go: High performance but smaller ecosystem
ADR 002: Microservices Architecture
Date: 2024-01-20 Status: Accepted Context: As the platform grows, we need to ensure scalability and maintainability. The monolithic architecture was becoming complex to manage and deploy. Decision: We decided to adopt a microservices architecture with the following services:- User Service
- Course Service
- Payment Service
- Notification Service
- Analytics Service
-
Positive:
- Independent deployment and scaling
- Technology diversity per service
- Better fault isolation
- Smaller, focused teams
-
Negative:
- Increased complexity in deployment and monitoring
- Distributed system challenges (consistency, latency)
- Higher operational overhead
- Monolithic with modules: Simpler but less scalable
- Serverless functions: Good scalability but vendor lock-in
ADR 003: API Design with REST
Date: 2024-01-25 Status: Accepted Context: We needed a consistent API design that would be easy to understand, version, and maintain for both internal and external consumers. Decision: We chose RESTful API design with the following principles:- Resource-based URLs
- Standard HTTP methods
- JSON responses
- OpenAPI/Swagger documentation
- Versioning through URL paths (/api/v1/)
-
Positive:
- Widely adopted and understood
- Good tooling support
- Easy to cache and debug
- Works well with HTTP infrastructure
-
Negative:
- Can lead to over-fetching/under-fetching
- Multiple round trips for complex data
- Less efficient for mobile networks
- GraphQL: More flexible but complex
- gRPC: High performance but language-specific
ADR 004: Database Schema Design
Date: 2024-02-01 Status: Accepted Context: We needed to design a database schema that supports the core business entities while maintaining data integrity and performance. Decision: We chose PostgreSQL with the following design principles:- Normalized schema to reduce redundancy
- UUID primary keys for scalability
- JSONB columns for flexible data
- Proper indexing strategy
- Foreign key constraints for data integrity
-
Positive:
- Strong data consistency
- Excellent JSON support for flexible data
- Advanced querying capabilities
- Good performance with proper indexing
-
Negative:
- More complex queries for denormalized data
- Migration complexity
- Learning curve for advanced features
- MongoDB: Flexible schema but weaker consistency
- MySQL: Familiar but less advanced features
ADR 005: Authentication with JWT
Date: 2024-02-05 Status: Accepted Context: We needed a secure and scalable authentication system that works well with microservices and mobile applications. Decision: We implemented JWT-based authentication with:- Access tokens with short expiration (1 hour)
- Refresh tokens for session management
- Role-based access control (RBAC)
- Secure token storage
-
Positive:
- Stateless authentication
- Works well with microservices
- Good mobile app support
- Industry standard
-
Negative:
- Token revocation complexity
- No server-side session invalidation
- Token size can be large
- Session-based auth: Server state management
- OAuth 2.0: More complex but more secure
ADR 006: Payment Processing with Stripe
Date: 2024-02-10 Status: Accepted Context: We needed a reliable payment processing solution that handles various payment methods and provides good developer experience. Decision: We integrated Stripe for payment processing with:- Support for multiple payment methods
- Webhook handling for payment events
- PCI compliance
- Subscription management
-
Positive:
- Excellent developer documentation
- Comprehensive API
- Strong security and compliance
- Good international support
-
Negative:
- Transaction fees
- Dependency on third-party service
- Webhook reliability concerns
- PayPal: Higher fees, less developer-friendly
- Braintree: Good but more complex integration
ADR 007: Deployment with Kubernetes
Date: 2024-02-15 Status: Proposed Context: We need a container orchestration solution that can handle our microservices deployment, scaling, and management. Decision: We are considering Kubernetes for container orchestration with:- Automated deployment and scaling
- Service discovery and load balancing
- Configuration management
- Monitoring and logging integration
-
Positive:
- Industry standard for container orchestration
- Highly scalable and reliable
- Rich ecosystem of tools
- Cloud-agnostic
-
Negative:
- Steep learning curve
- Complex setup and maintenance
- Resource overhead
- Docker Compose: Simple but not scalable
- AWS ECS: AWS-specific, less flexible
ADR Process
Creating a New ADR
- Identify Decision: Recognize when an architectural decision needs to be made
- Gather Context: Document the problem and constraints
- Evaluate Options: Consider multiple alternatives
- Make Decision: Choose the best option based on criteria
- Document ADR: Create ADR document following the template
- Review: Get feedback from team members
- Implement: Put the decision into practice
- Monitor: Track outcomes and adjust if needed
ADR Status Definitions
- Proposed: Decision is being considered
- Accepted: Decision has been made and implemented
- Rejected: Decision was considered but not chosen
- Deprecated: Decision is no longer relevant
- Superseded: Decision has been replaced by another
ADR Maintenance
- Review ADRs annually for relevance
- Update status when decisions change
- Link related ADRs for context
- Use ADRs for onboarding new team members
Tools and Templates
ADR Creation Script
ADR Template File (adr-template.md)
ADR 008: Beacon Analytics - Direct Database Writes
Date: 2025-01-15 Status: Accepted Context: The beacon analytics system tracks user engagement events (impressions, clicks, bounces) for marketplace entities. We needed to decide between:- Direct database writes on each event
- Queue-based processing with background workers
- Time-series database for analytics data
- Client-side batching (10 events or 2s timeout)
- Redis-based deduplication (prevents duplicate DB writes)
- Rate limiting (50 requests per 5 minutes per IP)
- Session-based authentication (reduces spam)
-
Positive:
- Simple architecture, easy to debug
- No additional infrastructure (queues, workers)
- Lower latency for real-time dashboards
- Fewer moving parts to maintain
-
Negative:
- DB load scales linearly with traffic
- Potential write contention at high scale
- No built-in retry mechanism for failed writes
- DB write latency consistently exceeds 50ms
- Traffic reaches ~1000 concurrent users (~10k events/min)
- Analytics queries start impacting main DB performance
- Phase 1: BullMQ queue with background worker (already in stack)
- Phase 2: Batch inserts (100-500 events per query)
- Phase 3: TimescaleDB for time-series optimization
- BullMQ Queue: Better scalability but added complexity
- Kafka: Enterprise-grade but overkill for current scale
- TimescaleDB: Excellent for analytics but migration overhead
- ClickHouse: High performance but operational complexity
- ADR 001: Technology Stack Selection
- ADR 004: Database Schema Design