Python Flask Celery Redis Docker PostgreSQL HTMX
A production-grade, containerized microservice architecture for preventing cold starts on free-tier hosting platforms
Features β’ Architecture β’ Tech Stack β’ Quick Start β’ API
- Overview
- Problem Statement
- System Architecture
- Core Features
- Technology Stack
- Installation & Setup
- Configuration
- Usage
- API Reference
- Performance Metrics
- Security
- Future Enhancements
WatchDog is a sophisticated, distributed uptime monitoring system engineered to solve the cold-start problem inherent in free-tier PaaS platforms (Render, Railway, Fly.io). Built on a microservices architecture, it leverages asynchronous task queues, scheduled workers, and real-time UI updates to ensure your services remain warm and responsive 24/7.
- Distributed Task Processing: Celery workers with Redis message broker
- Intelligent Scheduling: Cron-based task scheduling with configurable intervals
- Real-time Dashboard: HTMX-powered reactive UI with zero JavaScript frameworks
- Containerized Deployment: Multi-container Docker Compose orchestration
- Production Database: PostgreSQL with SQLAlchemy ORM
- HTTP/2 Support: curl-cffi for browser impersonation and TLS fingerprinting
- Graceful Failure Handling: Exponential backoff retry mechanism
Free-tier hosting platforms (Render, Railway, Heroku) spin down inactive services after 15 minutes of inactivity, causing:
- Cold Start Latency: 30-60 second response delays on first request
- Poor UX: Users experience timeouts and failed requests
- Lost Opportunities: Recruiters/clients abandon slow-loading portfolio sites
WatchDog solves this by periodically pinging your services at configurable intervals, keeping them perpetually warm and responsive.
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β WatchDog System β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
ββββββββββββββββ ββββββββββββββββ ββββββββββββββββ
β β β β β β
β Flask Web βββββββββββ€ Redis ββββββββββΊβCelery Worker β
β Server β β Message β β Pool β
β (Port 5000)β β Broker β β (Async) β
β β β (Port 6379) β β β
ββββββββ¬ββββββββ ββββββββββββββββ ββββββββ¬ββββββββ
β β
β β
β ββββββββββββββββ β
β β β β
ββββββββββββββββββΊβ PostgreSQL ββββββββββββββββββ
β Database β
β (Neon) β
β β
ββββββββββββββββ
β²γγγγ
β
ββββββββ΄ββββββββ
β β
β Celery Beat β
β Scheduler β
β (Cron Jobs) β
β β
ββββββββββββββββ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Request Flow Diagram β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
User Browser βββΊ Flask (HTMX) βββΊ PostgreSQL (Read/Write)
β
ββββΊ Redis βββΊ Celery Worker βββΊ HTTP Request
β β
β βΌ
β Target Service
β β
ββββββββββββββββββββ
(Update Status)
| Component | Technology | Purpose |
|---|---|---|
| Web Server | Flask + Gunicorn | REST API & UI rendering |
| Message Broker | Redis | Task queue & pub/sub |
| Task Workers | Celery | Async HTTP request execution |
| Scheduler | Celery Beat | Cron-based task scheduling |
| Database | PostgreSQL (Neon) | Persistent storage |
| Frontend | HTMX + TailwindCSS | Reactive SPA-like experience |
| Containerization | Docker Compose | Multi-service orchestration |
- Zero-JavaScript Framework: Pure HTMX for reactive updates
- Real-time Polling: Auto-refresh every 5 seconds without page reload
- Responsive Design: Mobile-first TailwindCSS styling
- Smooth Animations: CSS keyframe animations with staggered delays
- Dark Theme: Custom dot-grid background with glassmorphism effects
- HTTP Basic Auth: Password-protected admin dashboard
- Asynchronous Task Queue: Celery with Redis broker
- Intelligent Scheduling: Per-target configurable ping intervals
- Retry Logic: Exponential backoff (3 retries, 15s delay)
- Browser Impersonation: curl-cffi for bypassing bot detection
- ORM Layer: SQLAlchemy for database abstraction
- Environment Variables: python-dotenv for configuration management
- Multi-Stage Dockerfile: Optimized Python 3.13 image
- Docker Compose: 4-service orchestration (web, worker, beat, redis)
- Health Checks: Container dependency management
- Volume Persistence: Redis data persistence
- Network Isolation: Internal Docker network
Flask 3.0 # Lightweight WSGI web framework Flask-SQLAlchemy # ORM integration python-dotenv # Environment variable management
Celery 5.3 # Distributed task queue Redis 7.0 # Message broker & result backend celery-beat # Periodic task scheduler
PostgreSQL 16 # Production-grade RDBMS psycopg2-binary # PostgreSQL adapter Neon Database # Serverless Postgres hosting
curl-cffi # HTTP/2 client with browser impersonation requests # Fallback HTTP library
HTMX 1.9 # Hypermedia-driven interactions TailwindCSS 3.0 # Utility-first CSS framework Idiomorph # DOM morphing for smooth updates
Docker 24.0 # Containerization Docker Compose 3.8 # Multi-container orchestration
- Docker & Docker Compose installed
- Python 3.13+ (for local development)
- PostgreSQL database (or use Neon free tier)
- Redis server (or use Docker)
# Clone the repository git clone https://github.com/indiser/WatchDog.git cd WatchDog # Create environment file cat > .env << EOF DATABASE_URL=postgresql://user:pass@host:5432/dbname ADMIN_USER=admin ADMIN_PASS=your_secure_password CELERY_BROKER_URL=redis://redis:6379/0 EOF # Build and start all services docker-compose up --build -d # View logs docker-compose logs -f # Access dashboard open http://localhost:5000
# Create virtual environment python -m venv env source env/bin/activate # Windows: env\Scripts\activate # Install dependencies pip install -r requirements.txt # Set environment variables export DATABASE_URL="postgresql://..." export ADMIN_USER="admin" export ADMIN_PASS="password" export CELERY_BROKER_URL="redis://localhost:6379/0" # Terminal 1: Start Flask python app.py # Terminal 2: Start Celery Worker celery -A tasks.celery worker --pool=solo --loglevel=info # Terminal 3: Start Celery Beat celery -A tasks.celery beat --loglevel=info
| Variable | Description | Default |
|---|---|---|
DATABASE_URL |
PostgreSQL connection string | sqlite:///local_test.db |
CELERY_BROKER_URL |
Redis connection URL | redis://localhost:6379/0 |
ADMIN_USER |
Dashboard username | admin |
ADMIN_PASS |
Dashboard password | super_secret_default |
services: redis: # Message broker (port 6379) web: # Flask application (port 5000) worker: # Celery task executor beat: # Celery scheduler
class TargetURL(db.Model): id # Primary key url # Target URL to monitor interval_minutes # Ping frequency (default: 5) is_active # Enable/disable monitoring last_pinged_at # Last successful ping timestamp
- Navigate to
http://localhost:5000 - Enter credentials (ADMIN_USER / ADMIN_PASS)
- Input target URL and interval (minutes)
- Click "Monitor"
- Real-time Stats: Total/Active/Paused targets
- Target Management: Toggle active status, delete targets
- Live Updates: Auto-refresh every 5 seconds
- Mobile Responsive: Card layout on small screens
# Celery Beat runs every minute @celery.task def queue_due_pings(): # Check each active target # If (now - last_ping) >= interval: # Queue ping_url.delay(url) # Update last_pinged_at
All endpoints require HTTP Basic Auth.
Returns the main dashboard HTML.
Add a new monitoring target.
Form Data:
url: string (required)
interval_minutes: integer (default: 5)
Returns HTMX-compatible table body HTML.
Removes a target from monitoring.
Toggles target active/paused status.
Returns real-time statistics HTML fragment.
- Concurrent Workers: Configurable Celery pool size
- Request Throughput: 100+ pings/minute per worker
- Database Connections: SQLAlchemy connection pooling
- Memory Footprint: ~150MB per container
- Retry Mechanism: 3 attempts with 15s exponential backoff
- Timeout Handling: 10s HTTP timeout per request
- Graceful Degradation: Failed pings don't block queue
# Check Celery worker status celery -A tasks.celery inspect active # View Redis queue length redis-cli LLEN celery # Monitor container health docker-compose ps
- β HTTP Basic Authentication: Password-protected dashboard
- β
Environment Variables: Secrets stored in
.env(gitignored) - β SQL Injection Prevention: SQLAlchemy ORM parameterization
- β CSRF Protection: Form-based actions only
- β Docker Network Isolation: Internal service communication
- Use strong passwords for
ADMIN_PASS - Enable HTTPS with reverse proxy (Nginx/Caddy)
- Rotate database credentials regularly
- Implement rate limiting for production
- Use secrets management (AWS Secrets Manager, Vault)
- Webhook Notifications: Slack/Discord alerts on downtime
- Prometheus Metrics: Grafana dashboard integration
- Multi-User Support: Role-based access control
- Response Time Tracking: Historical latency graphs
- Status Page: Public uptime dashboard
- API Key Authentication: RESTful API access
- Kubernetes Deployment: Helm charts for K8s
- Email Alerts: SMTP integration for notifications
- Implement comprehensive unit tests (pytest)
- Add CI/CD pipeline (GitHub Actions)
- Database migration system (Alembic)
- API rate limiting (Flask-Limiter)
- Logging aggregation (ELK stack)
WatchDog/
βββ app.py # Flask application & routes
βββ tasks.py # Celery tasks & scheduling
βββ requirements.txt # Python dependencies
βββ dockerfile # Container image definition
βββ docker-compose.yml # Multi-service orchestration
βββ .env # Environment variables (gitignored)
βββ static/
β βββ style.css # Custom CSS animations
βββ templates/
β βββ index.html # Main dashboard
β βββ _stats_bar.html # Stats component
β βββ _target_row.html # Table row partial
β βββ ... # Other HTMX partials
βββ README.md # This file
Contributions are welcome! Please follow these steps:
- Fork the repository
- Create a feature branch (
git checkout -b feature/AmazingFeature) - Commit changes (
git commit -m 'Add AmazingFeature') - Push to branch (
git push origin feature/AmazingFeature) - Open a Pull Request
This project is licensed under the MIT License - see the LICENSE file for details.
Indiser
- GitHub: indiser
- Email: indiser01@gmail.com
- Flask team for the excellent web framework
- Celery project for distributed task processing
- HTMX for revolutionizing frontend interactivity
- TailwindCSS for rapid UI development
- Neon for serverless PostgreSQL hosting