A production-ready website uptime monitoring system that continuously checks endpoints, detects downtime using incident-based logic, and sends alerts when services go down and recover.
- Features
- Why WatchTower
- How It Works
- Architecture Highlights
- Tech Stack
- Data Model
- Prerequisites
- Installation
- Usage
- Contributing
- License
- Contact
- Automated Uptime Checks: HTTP/HTTPS endpoint monitoring with configurable intervals and timeouts.
- Incident-Based Downtime Detection: Avoids false positives and alert spam by using incident lifecycles.
- Email Alerts: Notifications for incident start (DOWN) and resolution (UP).
- Derived Status: Status is computed from real data, not stored flags.
- Secure Background Worker: Protected by secret headers for serverless execution.
- Serverless-Friendly: Designed for predictable costs and no long-running processes.
Unlike basic monitoring demos that simply ping URLs and toggle status flags, WatchTower is built like a real monitoring system. It incorporates background workers, incident lifecycles, alert deduplication, and serverless-safe execution, making it suitable for SaaS foundations, internal tools, or reference architectures for cron-driven systems.
The system operates continuously without manual intervention: GitHub Actions (cron) ↓ Secure Worker API (/api/worker/checks) ↓ HTTP checks + optimistic locking ↓ check_results → incidents ↓ Email alerts (DOWN / UP)
- Incident Model: Incidents open after consecutive failures and close on recovery.
- Optimistic Locking: Prevents duplicate checks in concurrent runs.
- Alert Deduplication: One alert per incident, with retries on delivery failure.
- Hard Execution Limits: Bounded work per cron run for predictable serverless costs.
These patterns mirror those in professional monitoring platforms.
- Next.js (App Router)
- TypeScript
- Tailwind CSS / shadcn/ui
- Supabase (PostgreSQL, Auth, RLS)
- GitHub Actions (cron jobs)
- Vercel (deployment)
- Email via Resend
- monitors: Configuration (URL, interval, timeout)
- check_results: Append-only check history
- incidents: Open/resolved downtime periods
- alerts: Alert delivery tracking
Status is derived from data, never stored explicitly.
- Node.js (version 18 or higher)
- pnpm
- Supabase account
- Resend account (for email alerts)
- Clone the repository:
git clone https://github.com/yourusername/watchtower.git cd watchtower - Install dependencies:
pnpm install
- Set up environment variables:
Create a
.env.localfile in the root directory and add the following variables:NEXT_PUBLIC_SUPABASE_URL=your_supabase_url NEXT_PUBLIC_SUPABASE_ANON_KEY=your_supabase_anon_key SUPABASE_SERVICE_ROLE_KEY=your_supabase_service_role_key RESEND_API_KEY=your_resend_api_key WORKER_SECRET_HEADER=your_worker_secret_header_value
- Set up Supabase:
- Create a new Supabase project.
- Run the SQL migrations located in the
supabase/migrationsdirectory to set up the database schema.
- Deploy the application:
- You can deploy the Next.js application to Vercel or any other hosting provider that supports Next.js.
- Add monitors via the web interface.
- The GitHub Actions cron job will automatically run the background worker to perform checks and handle incidents
- Monitor email alerts for downtime notifications.
Contributions are welcome! Please open issues and submit pull requests for improvements or bug fixes.
This project is licensed under the MIT License. See the LICENSE file for details.
For questions or support, please open an issue on GitHub or contact the maintainer at your email address. Anurag Poonia - GitHub