Lightweight endpoint monitoring with Telegram alerts. Single binary, zero dependencies.
- Multi-protocol - HTTP, JSON-RPC, gRPC, Tendermint, TCP, WebSocket
- Flexible HTTP - Any method, custom headers, request body, auth
- Response validation - Status codes, body contains, regex, JSON path
- Authentication - Basic auth, Bearer token
- TLS options - Skip verification for self-signed certs
- Per-endpoint config - Custom timeout, headers per endpoint
- Environment variables - Use
${VAR}syntax in config - Telegram alerts - Instant down/up/slow notifications
- Summary reports - Daily/weekly uptime summaries
- Webhook notifications - Slack, Discord, PagerDuty
- Web dashboard - Status, charts, incident history
- Prometheus metrics -
/metricsendpoint for scraping - Maintenance windows - Scheduled/acknowledged incident suppression
- Single binary - No runtime dependencies
go install github.com/ajansari95/pulse@latest# Create config
cat > config.yaml << 'EOF'
telegram:
bot_token: ""
chat_id: ""
notifications:
slack:
webhook_url: "https://hooks.slack.com/..."
discord:
webhook_url: "https://discord.com/api/webhooks/..."
pagerduty:
routing_key: "your-integration-key"
settings:
check_interval: "60s"
failure_threshold: 2
endpoints:
- name: "My API"
url: "https://api.example.com/health"
type: "http"
EOF
# Set credentials
export TELEGRAM_BOT_TOKEN="your-token"
export TELEGRAM_CHAT_ID="your-chat-id"
# Run
pulse config.yamlsettings:
check_interval: "60s" # How often to check
failure_threshold: 2 # Alert after N consecutive failures
slow_threshold: "5s" # Alert if response exceeds this
timeout: "10s" # Default request timeout
port: "8080" # Health endpoint port
metrics_port: "9090" # Metrics endpoint port (optional)
daily_summary: "09:00" # Daily summary time (local)
weekly_summary: "monday 09:00" # Weekly summary schedule (local)
public_dashboard: true # Enable the web dashboard
region: "us-east-1" # Region name for multi-region checks
coordinator_url: "" # Coordinator URL (agent mode)
regions_required: 2 # Minimum regions to alert
region_alerts: false # Coordinator sends per-region alerts
report_stale_after: "5m" # Ignore stale region reportsmaintenance:
- name: "Weekly deploy"
schedule: "sunday 02:00-04:00"
endpoints: ["API", "Database"]endpoints:
# Simple GET
- name: "API"
url: "https://api.example.com/health"
type: "http"
# POST with body and headers
- name: "API POST"
url: "https://api.example.com/check"
type: "http"
method: "POST"
content_type: "application/json"
body: '{"check": true}'
headers:
X-Custom: "value"
# Response validation
- name: "API Validated"
url: "https://api.example.com/status"
type: "http"
expected: 200
contains: "healthy"
json_path: "status"
json_path_value: "ok"
# Multiple valid status codes
- name: "Flexible API"
url: "https://api.example.com/endpoint"
type: "http"
expected_codes: [200, 201, 204]
# Regex match
- name: "Version"
url: "https://api.example.com/version"
type: "http"
match_regex: "v[0-9]+\\.[0-9]+"endpoints:
- name: "API"
url: "https://api.example.com/health"
type: "http"
latency:
p50_threshold: "200ms"
p95_threshold: "500ms"
p99_threshold: "1s"
window: "5m"endpoints:
# Bearer token
- name: "Protected API"
url: "https://api.example.com/admin"
type: "http"
bearer_token: "${API_TOKEN}"
# Basic auth
- name: "Admin API"
url: "https://internal.example.com/admin"
type: "http"
basic_auth:
username: "${ADMIN_USER}"
password: "${ADMIN_PASS}"endpoints:
- name: "Internal"
url: "https://internal.local:8443/health"
type: "http"
skip_tls_verify: true
timeout: "5s"endpoints:
# JSON-RPC (Ethereum, etc.)
- name: "Ethereum"
url: "https://eth.example.com"
type: "jsonrpc"
rpc_method: "eth_blockNumber"
# Tendermint/Cosmos
- name: "Cosmos"
url: "https://rpc.cosmos.example.com"
type: "tendermint"
# gRPC
- name: "gRPC Service"
url: "grpc.example.com:443"
type: "grpc"
# TCP port
- name: "Database"
url: "db.example.com"
type: "port"
port: 5432
# TCP direct
- name: "Redis"
url: "redis.example.com:6379"
type: "tcp"
# WebSocket
- name: "WS API"
url: "wss://ws.example.com/stream"
type: "websocket"Use ${VAR} in config - they expand at load time:
endpoints:
- name: "API"
url: "${API_URL}/health"
bearer_token: "${API_TOKEN}"Override settings via env:
TELEGRAM_BOT_TOKENTELEGRAM_CHAT_IDCHECK_INTERVALPORTMETRICS_PORTPUBLIC_DASHBOARDREGIONCOORDINATOR_URLREGIONS_REQUIREDREGION_ALERTSREPORT_STALE_AFTER
Expose metrics for scraping at GET /metrics. If metrics_port is set, metrics are served on that port; otherwise, they are served on the main HTTP port.
The dashboard is served at / and /dashboard when enabled. It provides real-time status, response-time charts, and incident history.
API endpoints:
/api/summaryfor status and aggregate metrics/api/historyfor response history and incidents
Run multiple Pulse agents and point them at a coordinator for aggregated alerting.
Coordinator:
settings:
region: "coordinator"
regions_required: 2
region_alerts: trueAgent:
settings:
region: "us-east-1"
coordinator_url: "http://coordinator:8080"Pulse can also send alerts to Slack, Discord, and PagerDuty. Configure the webhook URLs or routing key under notifications in your config.
Monitor certificate expiry with a dedicated ssl endpoint type:
endpoints:
- name: "API SSL"
url: "https://api.example.com"
type: "ssl"
warn_days: 30
critical_days: 7| Type | Check Method |
|---|---|
http |
HTTP request with configurable method/headers/body |
jsonrpc |
JSON-RPC 2.0 POST |
tendermint |
Tendermint /status endpoint |
grpc |
gRPC health check |
port / tcp |
TCP connection |
websocket |
TCP connection to WS endpoint |
ssl |
TLS certificate expiry check |
- Message @BotFather →
/newbot - Copy the token
- Add bot to your channel/group as admin
- Get chat ID: forward a message to @userinfobot
/status- Current status summary/mute <endpoint> <duration>- Mute alerts (example:/mute API 30m)/ack <endpoint>- Acknowledge an incident/maintenance start <endpoint> <duration>- Start a maintenance window (example:/maintenance start API 2h)
Send /status in chat to get current status.
curl http://localhost:8080/healthReturns JSON with all endpoint statuses. Returns 503 if any endpoint is down.
docker run -d \
-e TELEGRAM_BOT_TOKEN="xxx" \
-e TELEGRAM_CHAT_ID="xxx" \
-v $(pwd)/config.yaml:/config.yaml \
ghcr.io/ajansari95/pulseMIT