> your AI agent picks dependencies from memory; give it dated facts — try starlog.dev ↗ vet your agent's deps ↗ vibe-coding is fine. vibe-importing isn’t. — try starlog.dev ↗ vibe-importing isn’t fine ↗ your agent has never seen your private packages — try starlog.dev ↗ facts for private packages ↗ a linter for the dependencies your AI agent picks — try starlog.dev ↗ a linter for agent deps ↗ whois is redacted, cdns mask the rest — get the real operator — try whoisgeni.us ↗ who really runs that domain ↗ domain attribution that shows its work — full evidence chain — try whoisgeni.us ↗ domain intel w/ evidence ↗

← Back to Articles

CheckCle: The PocketBase-Powered Monitoring Stack You Can Actually Deploy

[ View on GitHub ]

CheckCle: The PocketBase-Powered Monitoring Stack You Can Actually Deploy

Hook

Most monitoring platforms require assembling 5+ microservices before you can check if your website is up. CheckCle does it with one Docker command and a SQLite file.

Context

The monitoring landscape splits into two hostile camps: cloud SaaS tools that bill per endpoint (StatusPage, Better Uptime, Pingdom) and self-hosted behemoths that demand dedicated ops teams (Prometheus, Zabbix, Nagios). For the startup running 20 services or the indie developer monitoring side projects, both options are grotesque overkill.

CheckCle enters this gap with an audacious architectural bet: what if you built monitoring on top of PocketBase? PocketBase is essentially a batteries-included SQLite wrapper that auto-generates REST APIs, handles authentication, and provides real-time WebSocket subscriptions. By leveraging PocketBase as the foundation, CheckCle gets admin UI, real-time dashboards, and API scaffolding for free—letting the project focus exclusively on monitoring logic. The result is a genuinely self-hosted platform that deploys with docker run, stores everything in a single SQLite file, and requires zero configuration of message queues, time-series databases, or Kubernetes operators.

Technical Insight

Subscribe via WebSocket

Configure Monitors

Read/Write

Poll Active Monitors

Spawn Check Jobs

HTTP/DNS/Ping Probes

Write Results

Trigger on Failure

Notify

Push Updates

POST Metrics

TypeScript Frontend

PocketBase Core

Auth + REST + WebSocket

Go Scheduler

Goroutines per Monitor

Check Executors

HTTP/DNS/TCP/Ping

SQLite Database

Monitors/Results/Incidents

Remote Agents

Server Metrics

External Targets

Incident Creation Hooks

Loading...

System architecture — auto-generated

CheckCle's architecture is a masterclass in strategic laziness. The Go backend extends PocketBase rather than fighting it, registering custom collections for monitors, incidents, and metrics while letting PocketBase handle the HTTP routing and database migrations. Here's the conceptual model:

// Simplified example of how CheckCle registers a monitoring check
type HTTPCheck struct {
    URL            string        `json:"url"`
    Method         string        `json:"method"`
    Interval       time.Duration `json:"interval"`
    Timeout        time.Duration `json:"timeout"`
    ExpectedStatus int           `json:"expected_status"`
}

// Check executor runs in a goroutine per monitor
func (c *HTTPCheck) Execute(ctx context.Context) CheckResult {
    start := time.Now()
    
    req, _ := http.NewRequestWithContext(ctx, c.Method, c.URL, nil)
    resp, err := httpClient.Do(req)
    
    result := CheckResult{
        Latency:   time.Since(start),
        Timestamp: start,
        Success:   err == nil && resp.StatusCode == c.ExpectedStatus,
    }
    
    // PocketBase auto-generates API for this collection
    pb.Collection("check_results").Create(result)
    return result
}

The scheduler spawns a goroutine for each configured monitor, sleeping between checks based on the interval. When a check fails, the result triggers incident creation through PocketBase's collection hooks—essentially database triggers that fire Go functions. The frontend subscribes to the check_results collection via PocketBase's WebSocket endpoint and updates the dashboard in real-time without polling.

This architecture has profound implications. Because everything is a PocketBase collection, you get filtering, sorting, and pagination for free via auto-generated REST endpoints. Want to query the last 100 failed checks? That's just GET /api/collections/check_results/records?filter=(success=false)&sort=-created. The admin panel PocketBase provides becomes your monitoring configuration UI with zero custom code.

Distributed regional monitoring works through agent deployments rather than consensus protocols. You run CheckCle instances in multiple regions, each independently executing checks and writing results to their local SQLite database. A central aggregator (likely another CheckCle instance) polls these agents via API to build a global view. It's architecturally simple but means no distributed coordination—if two regions both detect downtime, you'll get duplicate alerts unless you implement deduplication in the notification layer.

The server monitoring agent follows the classic phone-home pattern:

# One-line agent installation (reconstructed from docs)
curl -fsSL https://checkcle.io/install.sh | sudo sh -s -- --token YOUR_API_TOKEN

# Agent runs as systemd service, posting metrics every 30s
while true; do
    curl -X POST https://your-checkcle.instance/api/metrics \
        -H "Authorization: Bearer $TOKEN" \
        -d '{"cpu": "'$(cpu_usage)'", "mem": "'$(mem_usage)'"}'
    sleep 30
done

Agents authenticate with API tokens and push metrics to the /api/metrics endpoint, which PocketBase routes to a custom handler that writes to the server_metrics collection. Because SQLite supports write concurrency (multiple readers, single writer with WAL mode), this scales to dozens of agents before write contention becomes measurable. Beyond a few hundred agents reporting every 30 seconds, you'll saturate SQLite's ~1000 writes/second ceiling and need to batch inserts or switch databases entirely.

The notification system hooks into PocketBase's record lifecycle events. When a check transitions from passing to failing, a beforeCreate hook on the incidents collection fires, evaluating notification rules and dispatching alerts via configured channels (email, Slack, webhooks). This event-driven architecture is elegant but means notification logic is tightly coupled to database writes—you can't easily implement complex routing like "escalate to PagerDuty only if incident persists for 5 minutes" without introducing state machines outside PocketBase's mental model.

Status pages work through public collection views. PocketBase supports unauthenticated read access to specific collections, so CheckCle exposes a /status route that queries the monitors and check_results collections with public visibility. The TypeScript frontend renders these as a branded status page with historical uptime percentages calculated client-side from the fetched records. It's brilliantly simple but means every status page view hammers SQLite with range queries—fine for dozens of concurrent viewers, problematic if your outage status page gets HackerNews-hugged.

Gotcha

SQLite is both CheckCle's superpower and its Achilles heel. The single-file database makes backups trivial (just copy one file) and eliminates operational complexity, but SQLite fundamentally can't scale horizontally. If you're monitoring 500 endpoints with 1-minute check intervals, you're writing 500 records/minute to check_results. Add 50 servers reporting metrics every 30 seconds (100 writes/minute) and you're at 600 writes/minute sustained—well within SQLite's capabilities. But enable 10-second health checks and suddenly you're at 3000+ writes/minute, approaching SQLite's practical write ceiling even with WAL mode and connection pooling. The file descriptor limits in deployment examples (nofile=4096:8192) exist because each active check goroutine maintains HTTP client connections, and the Go runtime keeps file descriptors open for SQLite WAL files.

The PocketBase dependency creates subtle lock-in. You're bound to its authentication model (user/admin roles, OAuth2), its API conventions (REST with specific query param syntax), and its migration system. If you need advanced features like metric downsampling, retention policies, or PromQL-style queries, you're implementing them outside PocketBase's framework—essentially writing a second database layer on top. The project's GitHub issues reveal users hitting these walls when trying to implement features like "delete check results older than 90 days" or "aggregate hourly averages," which require custom SQL that breaks PocketBase's abstraction.

Security-conscious teams will blanch at the agent installation pattern. Curling a shell script and piping to sudo sh is the monitoring equivalent of curl | bash—convenient but a supply chain attack waiting to happen. There's no mention of agent binary signing, checksum verification, or attestation. A compromised agent with API token access could flood fake metrics, enumerate your infrastructure topology via API responses, or potentially exploit vulnerabilities in the metrics ingestion endpoint to achieve code execution on the monitoring server.

Verdict

Use if: You're monitoring fewer than 100 services, value deployment simplicity over architectural flexibility, and need a self-hosted alternative to StatusPage without learning Prometheus. CheckCle is perfect for startups, indie hackers, and small ops teams who want zero-config monitoring that actually works. The PocketBase foundation means you get a working system in minutes, not days of YAML archaeology. Skip if: You're monitoring hundreds of endpoints with sub-minute intervals, need compliance audit trails that SQLite can't provide, or already run Prometheus/Grafana and would just be adding another monitoring silo. If your infrastructure demands true high availability with distributed consensus or you need advanced query capabilities like PromQL, CheckCle's architectural ceiling will frustrate you within months. For enterprise scale or regulated industries, the SQLite limitation and agent security model are non-starters—stick with battle-tested tools like Datadog or self-hosted Prometheus federation.