LearnFlow Architecture Deep Dive
· 3 min read
LearnFlow uses a modern, dual-database architecture that leverages the strengths of both SQL and NoSQL databases. In this post, we'll explore the technical decisions behind our architecture.
Why Dual Database Architecture?
LearnFlow uses both PostgreSQL and MongoDB to optimize for different data access patterns:
PostgreSQL (Relational) - Structured Data
Use Cases:
- User accounts and authentication
- Course metadata
- Enrollments
- Audit logs
- Discussion comments
Rationale:
- ACID Compliance: Critical for financial and user data
- Structured Relationships: Users → Courses → Enrollments
- Query Flexibility: Complex joins for analytics
- Maturity: Battle-tested for production systems
MongoDB (NoSQL) - Flexible Content
Use Cases:
- Course lessons (varying structures)
- User progress (variable per user)
- Rich content with different schemas
Rationale:
- Flexible Schema: Lessons can have different content types
- Scalability: Handle growing content libraries
- Document Model: Natural fit for lesson-progress relationships
- Rapid Development: Easy schema evolution
Frontend Architecture
Our frontend is built with:
- React 19: Modern UI component library with hooks
- Vite: Fast build tool and development server
- React Router: Client-side routing
- Tailwind CSS: Utility-first CSS framework
- Framer Motion: Animations and transitions
Key Frontend Patterns
- Context API: Used for global state management (Auth, Theme)
- Protected Routes: Role-based route protection
- Service Layer: Centralized API calls
- Component Composition: Reusable, composable components
Backend Architecture
Our backend is built with:
- FastAPI: Modern Python web framework
- SQLAlchemy: SQL ORM toolkit
- JWT: Token-based authentication
- bcrypt: Password hashing
- slowapi: Rate limiting
Key Backend Patterns
- Dependency Injection: FastAPI's Depends for database sessions
- Pydantic Schemas: Request/response validation
- Middleware: CORS, rate limiting, error handling
- Service Layer: Separated business logic
Authentication Flow
┌──────────┐ ┌──────────┐ ┌──────────┐
│ Client │ │ Backend │ │ Database │
└──────────┘ └──────────┘ └──────────┘
│ │ │
│ POST /login │ │
│─────────────────>│ │
│ │ Verify password │
│ │─────────────────>│
│ │ │
│ │<─────────────────│
│ │ │
│ │ Create JWT token │
│ │─────────────────>│
│ │ │
│<─────────────────│ │
│ JWT token │ │
Design Decisions
1. FastAPI over Flask/Django
Decision: Use FastAPI for the backend.
Rationale:
- Automatic OpenAPI documentation
- Native async support for better performance
- Type validation with Pydantic
- Modern Python features
2. React with Vite
Decision: Use React 19 with Vite build tool.
Rationale:
- Fast development server
- Optimized production builds
- Large ecosystem
- Modern hooks API
3. JWT over Sessions
Decision: Stateless JWT authentication.
Rationale:
- Scalable across multiple servers
- No session storage needed
- Mobile-friendly tokens
4. Dual Database
Decision: PostgreSQL + MongoDB.
Rationale:
- PostgreSQL for ACID-critical data (users, payments)
- MongoDB for flexible content (lessons, progress)
What's Next?
We're planning to evolve our architecture with:
- Microservices decomposition
- Event-driven architecture
- Advanced caching strategies
- Real-time features with WebSockets
Learn More
Check out our architecture documentation for more details.
