Skip to main content

Prerequisites

Before you begin, make sure you have the following installed:
go install github.com/pressly/goose/v3/cmd/goose@latest
You’ll also need SMTP credentials for email notifications. Services like Mailtrap, SendGrid, or your own SMTP server will work.

Installation

1

Clone the repository

Get the Watchdog source code from your repository:
git clone <your-repo-url>
cd watchdog
2

Install dependencies

Download all Go module dependencies:
go mod download
The project uses these key dependencies:
  • github.com/jackc/pgx/v5 - PostgreSQL driver
  • github.com/redis/go-redis/v9 - Redis client
  • github.com/urfave/cli/v3 - CLI framework
  • gopkg.in/mail.v2 - Email sending
3

Build the binary (optional)

You can either run with go run or build a binary:
go build -o watchdog ./cmd/...
This creates a watchdog executable you can run directly.

Configuration

1

Create environment file

Copy the example environment file and edit it with your settings:
cp .env.example .env
2

Configure database settings

Update these database variables in your .env file:
.env
DB_USER=tsdbadmin
DB_PASSWORD=your_password
DB_HOST=localhost
DB_PORT=5432
DB_DATABASE=tsdb
Make sure your PostgreSQL instance has the TimescaleDB extension installed. You can verify this by connecting to your database and running:
CREATE EXTENSION IF NOT EXISTS timescaledb;
3

Configure Redis

Set your Redis connection details:
.env
REDIS_HOST=127.0.0.1:6379
REDIS_PASS=''
REDIS_DB=2
4

Configure SMTP for notifications

Add your SMTP credentials for email alerts:
.env
MAIL_FROM_ADDRESS="[email protected]"
MAIL_HOST=sandbox.smtp.mailtrap.io
MAIL_PORT=2525
MAIL_USERNAME=your_username
MAIL_PASSWORD=your_password
5

Set worker configuration

Configure the monitoring system’s concurrency:
.env
MAXIMUM_CHILD_WORKERS=5
MAXIMUM_WORK_POOL_SIZE=25
HTTP_REQUEST_TIMEOUT=5
SUPERVISOR_POOL_FLUSH_TIMEOUT=5
SUPERVISOR_POOL_FLUSH_BATCHSIZE=100
MAXIMUM_CHILD_WORKERS controls how many concurrent checks run per interval group. MAXIMUM_WORK_POOL_SIZE sets the total concurrency limit across all workers.

Database setup

1

Run migrations

Create the required database tables using Goose:
goose -dir migrations up
This creates three tables:
  • urls - Stores monitored URL metadata
  • url_status - TimescaleDB hypertable for time-series metrics
  • incidents - Tracks downtime incidents
2

Verify tables

Connect to your database and verify the tables exist:
\dt
-- Should show: urls, url_status, incidents

Add your first URL

Now you’re ready to add a URL to monitor:
go run ./cmd/... add https://example.com get five_minutes [email protected]
The add command accepts four positional arguments:
  1. URL - The endpoint to monitor (required)
  2. HTTP method - get, post, patch, put, or delete (default: get)
  3. Frequency - How often to check (default: five_minutes)
  4. Contact email - Where to send alerts (required)

Available monitoring frequencies

  • ten_seconds - Check every 10 seconds
  • thirty_seconds - Check every 30 seconds
  • one_minute - Check every minute
  • five_minutes - Check every 5 minutes
  • thirty_minutes - Check every 30 minutes
  • one_hour - Check every hour
  • twelve_hours - Check twice daily
  • twenty_four_hours - Check once daily
When you add a URL, Watchdog automatically persists it to the database and refreshes the Redis interval list so workers can immediately start monitoring it.

Start monitoring

Launch the Watchdog monitoring service:
go run ./cmd/... guard
You should see output indicating the service has started:
Connected to PostgreSQL database!
Watchdog is running
The guard command:
  • Connects to Redis and PostgreSQL
  • Initializes the orchestrator and supervisor
  • Creates worker groups for all configured intervals
  • Starts monitoring all added URLs
  • Publishes events to the event bus
  • Listens for state changes and sends notifications
Keep the guard process running. If you stop it, monitoring will pause until you restart it. Consider using a process manager like systemd, supervisord, or Docker for production deployments.

Manage monitored URLs

List all URLs

View your monitored URLs with pagination and filtering:
go run ./cmd/... list --page=1 --per_page=20
Example output:
Page 1 (showing 2 results)
→ Next: --page=2
------------------------------------------------------------
1. https://example.com
   ID: 1 | Method: GET | Status: Healthy | Frequency: five_minutes
   Contact: [email protected]

2. https://api.example.com/health
   ID: 2 | Method: GET | Status: Healthy | Frequency: one_minute
   Contact: [email protected]

------------------------------------------------------------
More results available. Use --page=2 to continue.

Remove a URL

Stop monitoring a URL by its ID:
go run ./cmd/... remove 1
This deletes the URL from the database and refreshes the Redis list for that frequency interval.

Analyze a URL

Run an ad-hoc analysis on a monitored URL:
go run ./cmd/... analysis 1

What’s next?

Architecture deep dive

Learn how Watchdog’s event-driven system works under the hood

CLI reference

Explore all available commands and their options

Configuration

Fine-tune worker pools, timeouts, and monitoring behavior

Running service

Production deployment guides for Docker, systemd, and cloud platforms

Build docs developers (and LLMs) love