Overview
The database architecture consists of:- PostgreSQL - Primary relational database for URL metadata
- TimescaleDB - Time-series extension for storing monitoring metrics
- pgx - High-performance PostgreSQL driver and connection pool
- Goose - Database migration tool for schema management
Prerequisites
Install TimescaleDB
Install the TimescaleDB extension:
Using the official TimescaleDB Docker image is the easiest way to get started with both PostgreSQL and TimescaleDB pre-configured.
Database configuration
Configure database connection settings in your.env file:
.env
Environment variables
PostgreSQL username with permissions to create tables and extensions.
PostgreSQL password for authentication.
Database server hostname or IP address (
localhost for local development).Database server port (default PostgreSQL port is
5432).Name of the database to use for Watchdog.
Initial setup
Enable TimescaleDB extension
Connect to the database and enable TimescaleDB:
The TimescaleDB extension must be enabled before running migrations, as migrations create hypertables that depend on it.
Database schema
Watchdog uses three main tables:URLs table
Stores metadata for monitored URLs:migrations/20251115112101_create_urls_table.sql
id- Unique identifier for the URLurl- The URL being monitoredhttp_method- HTTP method to use (get,post,patch,put,delete)status- Current health status (healthy,unhealthy,pending)monitoring_frequency- Check interval (ten_seconds,one_minute,five_minutes, etc.)contact_email- Email address for status change notificationscreated_at/updated_at- Timestamps
URL statuses table (hypertable)
Stores time-series monitoring metrics:migrations/20251208081023_create_url_status_table.sql
time- Timestamp of the check (hypertable partition key)url_id- Foreign key tourlstablestatus- Check result (truefor success,falsefor failure)
create_hypertable() converts this table into a TimescaleDB hypertable, enabling efficient time-series queries and automatic partitioning.Incidents table (hypertable)
Tracks downtime incidents:migrations/20251213095702_create_incidents_table.sql
time- Incident start time (hypertable partition key)url_id- Foreign key to monitored URLresolved_at- Timestamp when incident was resolved (NULL for ongoing incidents)
Connection pooling
Watchdog usespgxpool for efficient connection management:
Connection pool configuration
Thepgxpool library automatically manages connection pooling with sensible defaults. You can customize pool behavior by modifying the connection string:
- Max connections: Determined by server resources (typically 4-10)
- Min connections: 0 (connections created on demand)
- Connection lifetime: Unlimited
- Idle timeout: Unlimited
For most deployments, the default settings are sufficient. Tune pool size based on your concurrency requirements and database server capacity.
Repository pattern
Watchdog uses the repository pattern to abstract database operations:- Decouples business logic from SQL
- Enables easy testing with mock repositories
- Provides type-safe database operations
- Centralizes query logic
Migrations
Watchdog uses Goose for schema versioning and migrations.Running migrations
Migration file structure
Migrations follow the Goose format with-- +goose Up and -- +goose Down directives:
TimescaleDB features
TimescaleDB provides powerful time-series capabilities:Automatic partitioning
Hypertables are automatically partitioned by time for optimal query performance:Data retention policies
Automatically drop old data to manage storage:Continuous aggregates
Pre-compute aggregations for fast queries:Continuous aggregates are optional but highly recommended for large-scale deployments with many monitored URLs.
Troubleshooting
Connection refused errors
Connection refused errors
Symptoms:
pgxpool connection failed: connection refusedSolutions:- Verify PostgreSQL is running:
sudo systemctl status postgresql - Check PostgreSQL is listening on the correct port:
sudo netstat -tlnp | grep 5432 - Verify
pg_hba.confallows connections from your host - Check firewall rules allow port 5432
TimescaleDB extension not found
TimescaleDB extension not found
Symptoms:
ERROR: extension "timescaledb" is not availableSolutions:- Install TimescaleDB extension package
- Run
timescaledb-tuneto configure PostgreSQL - Add
shared_preload_libraries = 'timescaledb'topostgresql.conf - Restart PostgreSQL:
sudo systemctl restart postgresql
Migration failures
Migration failures
Symptoms: Goose migrations fail or leave database in inconsistent stateSolutions:
- Check migration status:
goose status - Manually fix the database schema
- Update
goose_db_versiontable to reflect actual state - Re-run migrations:
goose up
Connection pool exhaustion
Connection pool exhaustion
Symptoms:
all pool connections are in use errors under high loadSolutions:- Increase pool size in connection configuration
- Reduce
MAXIMUM_WORK_POOL_SIZEto limit concurrency - Check for connection leaks (connections not properly closed)
- Increase PostgreSQL
max_connectionssetting