FeedForward is designed as a monolithic web application with a focus on simplicity, privacy, and educational effectiveness. The architecture prioritizes ease of deployment, minimal operational overhead, and clear separation of concerns while providing sophisticated AI-powered feedback capabilities.
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ Web Browser โ
โ (Student/Instructor/Admin) โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ HTTPS
โโโโโโโโโโโโโโโโโโโโโโโโโโโดโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ FastHTML Application โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ Presentation Layer โ โ
โ โ (FastHTML + HTMX + Tailwind CSS) โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโดโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ Application Layer โ โ
โ โ (Routes, Controllers, Business Logic) โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโดโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ Service Layer โ โ
โ โ (Auth, Feedback Gen, Email, File Processing) โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโดโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ Data Layer โ โ
โ โ (FastLite ORM + SQLite Database) โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ
โโโโโโโโโโโโโโโโโโโโโโโดโโโโโโโโโโโโโโโโโ
โ โ
โโโโโโโโโดโโโโโโโโโโ โโโโโโโโโโโดโโโโโโโโโ
โ External APIs โ โ File Storage โ
โ (LLM Providers)โ โ (Local Disk) โ
โโโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโโ
Core Framework:
Language: Python 3.8+
Web Framework: FastHTML (FastAPI + Starlette)
Template Engine: FastHTML components
Frontend: HTMX for interactivity
Styling: Tailwind CSS
Database:
Engine: SQLite 3
ORM: FastLite
Migrations: Custom SQL scripts
External Services:
AI/LLM: LiteLLM (multi-provider)
Email: SMTP
File Processing: Python libraries
Infrastructure:
Server: Uvicorn ASGI
Process Manager: systemd/supervisor
Reverse Proxy: nginx (recommended)
FeedForward follows a modified MVC pattern:
Models (app/models/)
โโโ User, Course, Assignment, Draft
โโโ AIModel, FeedbackResult
โโโ Database schema definitions
Views (app/templates/ + FastHTML components)
โโโ Server-side rendered HTML
โโโ HTMX partial updates
โโโ Tailwind CSS styling
Controllers (app/routes/)
โโโ Route handlers by role
โโโ Business logic coordination
โโโ Response generation
Key services are isolated for maintainability:
Services (app/services/)
โโโ AuthService - Authentication/authorization
โโโ FeedbackGenerator - AI feedback orchestration
โโโ EmailService - Notification delivery
โโโ FileHandler - Upload/content extraction
โโโ PrivacyService - Data cleanup/retention
โโโ AnalyticsService - Progress tracking
-- Core Educational Hierarchy
users (id, email, role, status...)
โโโ instructors โ courses
โโโ assignments
โโโ drafts (student submissions)
โโโ feedback_results
-- AI Configuration
ai_providers (api keys, config)
โโโ ai_models
โโโ assignment_model_runs
โโโ model_feedback_results
-- Supporting Tables
rubric_templates
rubric_criteria
course_students
invitations
audit_logs
Student Submission Flow:
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
1. File Upload
Browser โ FastHTML โ FileHandler โ Disk Storage
2. Content Processing
File โ Extractor โ Draft Record โ Database
3. AI Feedback Generation
Draft โ FeedbackGenerator โ LLM APIs โ Results
4. Instructor Review
Results โ Review Interface โ Approval โ Student
5. Privacy Cleanup
Scheduled Task โ Remove Content โ Keep Metadata
All major entities follow a consistent lifecycle:
Status Progression:
draft โ active โ inactive โ archived โ deleted
Soft Deletion:
- Records never physically deleted
- Status field indicates state
- Deleted_at timestamp when removed
- Cascade rules for dependent entities
Example - Course Lifecycle:
draft: Being created
active: Students can access
inactive: No new submissions
archived: Read-only access
deleted: Hidden from all users
Authentication Flow:
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
1. Email/Password Login
โโโ Verify credentials
โโโ Create session
โโโ Set secure cookie
2. Role-Based Access Control
Admin: Full system access
Instructor: Course management
Student: Assignment submission
3. Route Protection
@admin_required
@instructor_required
@student_required
API Key Management:
Storage: Encrypted in database
Encryption: Fernet (symmetric)
Key Derivation: PBKDF2HMAC from SECRET_KEY
Access: Decrypted only when needed
Student Data Privacy:
Submissions: Temporarily stored
Cleanup: Automatic after feedback
Retention: Metadata only
Access: Student + Instructor only
Session Security:
Cookie: HTTPOnly, Secure, SameSite
Timeout: Configurable (default 24h)
Storage: Server-side sessions
AI Model Hierarchy:
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Provider Level (OpenAI, Anthropic, etc.)
โโโ API Configuration
โโโ Authentication
โโโ Rate Limiting
Model Level (GPT-4, Claude-3, etc.)
โโโ Capabilities
โโโ Default Parameters
โโโ Cost Information
Instance Level (Per Assignment Config)
โโโ Temperature Settings
โโโ Token Limits
โโโ Custom Prompts
โโโ Number of Runs
# Simplified feedback generation flow
async def generate_feedback(draft_id):
# 1. Load assignment configuration
assignment = get_assignment_settings(draft_id)
# 2. Execute multiple model runs
results = []
for model in assignment.models:
for run in range(model.num_runs):
result = await call_llm(
model=model,
prompt=build_prompt(draft, rubric),
parameters=model.parameters
)
results.append(result)
# 3. Aggregate results
final_feedback = aggregate_results(
results,
method=assignment.aggregation_method
)
# 4. Store and notify
save_feedback(final_feedback)
notify_instructor(draft_id)
Concurrent Users: ~1,000 active
Total Users: ~20,000 accounts
Requests/Second: ~100
Database Size: ~10GB practical limit
File Storage: Local disk dependent
Vertical Scaling (Current):
โโโ Increase server resources
โโโ Optimize database queries
โโโ Add caching layer
โโโ Tune worker processes
Future Horizontal Scaling:
โโโ PostgreSQL migration
โโโ S3 file storage
โโโ Redis session store
โโโ Load balancer
โโโ Background job queue
Recommended Production Setup:
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ nginx (Reverse Proxy) โ
โ - SSL termination โ
โ - Static file serving โ
โ - Rate limiting โ
โโโโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโ
โ
โโโโโโโโโโโโโโโโโโดโโโโโโโโโโโโโโโโโ
โ Uvicorn (ASGI Server) โ
โ - Multiple workers โ
โ - Process management โ
โโโโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโ
โ
โโโโโโโโโโโโโโโโโโดโโโโโโโโโโโโโโโโโ
โ FeedForward Application โ
โ - FastHTML app โ
โ - SQLite database โ
โ - Local file storage โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
/opt/feedforward/
โโโ app/ # Application code
โโโ data/
โ โโโ feedforward.db # SQLite database
โ โโโ uploads/ # Temporary files
โโโ logs/ # Application logs
โโโ backups/ # Database backups
โโโ venv/ # Python virtual environment
# Background task example
@background_task
async def process_draft_submission(draft_id):
try:
# Update status
update_draft_status(draft_id, "processing")
# Generate feedback
await generate_feedback(draft_id)
# Cleanup
schedule_content_removal(draft_id)
except Exception as e:
update_draft_status(draft_id, "error")
log_error(e)
Scheduled Jobs:
Privacy Cleanup:
Schedule: Every hour
Action: Remove old submission content
Database Optimization:
Schedule: Daily at 2 AM
Action: VACUUM and ANALYZE
Usage Reports:
Schedule: Weekly
Action: Generate analytics
Backup:
Schedule: Daily at 3 AM
Action: Database backup
Cache Layers:
Application Cache:
- Rubric templates
- AI model configurations
- User permissions
Database Query Cache:
- Prepared statements
- Connection pooling
- Index optimization
Frontend Cache:
- Static assets (1 year)
- HTMX partials (5 minutes)
- API responses (varies)
-- Key indexes for performance
CREATE INDEX idx_drafts_assignment_student
ON drafts(assignment_id, student_id);
CREATE INDEX idx_feedback_draft
ON feedback_results(draft_id);
CREATE INDEX idx_courses_instructor
ON courses(instructor_id, status);
-- Partitioning strategy (future)
-- Partition by academic year for historical data
User Errors (4xx):
- Invalid input โ Clear error message
- Unauthorized โ Redirect to login
- Not found โ Helpful 404 page
System Errors (5xx):
- Database error โ Retry + fallback
- AI API failure โ Queue for retry
- Server error โ Error page + logging
External Service Errors:
- LLM timeout โ Fallback model
- Email failure โ Retry queue
- File processing โ Error notification
# Resilient service pattern
async def call_ai_with_fallback(prompt, models):
for model in models:
try:
return await model.generate(prompt)
except (Timeout, APIError):
continue
# All models failed
return queue_for_manual_review(prompt)
Application Metrics:
- Request rate and latency
- Error rates by endpoint
- Active user sessions
- Background job success rate
Business Metrics:
- Submissions per day
- Feedback generation time
- AI API usage and costs
- User engagement rates
System Metrics:
- CPU and memory usage
- Database query performance
- Disk usage and I/O
- Network throughput
Log Streams:
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Application Logs โ /logs/app.log
- User actions
- Business events
- Errors and warnings
Access Logs โ /logs/access.log
- HTTP requests
- Response times
- Status codes
Audit Logs โ Database
- Security events
- Data modifications
- Permission changes
AI Logs โ /logs/ai_calls.log
- Model calls
- Token usage
- Response times
Near-term (6 months):
- Redis caching layer
- PostgreSQL migration option
- S3-compatible file storage
- Enhanced monitoring (Prometheus)
Medium-term (1 year):
- Microservices extraction
- API-first architecture
- Real-time notifications (WebSockets)
- Advanced analytics pipeline
Long-term (2+ years):
- Multi-tenant SaaS option
- Kubernetes deployment
- Event-driven architecture
- Machine learning pipeline
SQLite โ PostgreSQL:
- Export/import scripts
- Connection string change
- Query compatibility layer
- Gradual migration support
Monolith โ Services:
- Extract feedback service first
- API gateway pattern
- Shared database initially
- Event bus for communication
Key architectural decisions are documented in ADRs:
This architecture is designed for institutional deployment with 1,000-20,000 users. For larger scales, consider the migration paths outlined above.