supabase-observability
Set up monitoring and observability for Supabase projects using Dashboard reports, CLI inspect commands, pg_stat_statements, log drains, and alerting. Use when implementing monitoring, diagnosing slow queries, forwarding logs, or configuring alerts for Supabase project health. Trigger with phrases like "supabase monitoring", "supabase metrics", "supabase observability", "supabase logs", "supabase alerts", "supabase inspect", "supabase log drain".
What this skill does
# Supabase Observability
## Overview
Monitor Supabase projects end-to-end: Dashboard reports for API/database/auth metrics, `supabase inspect db` CLI for deep Postgres diagnostics, `pg_stat_statements` for query analytics, log drains for external aggregation, Edge Functions for custom metrics, and alerting on quota thresholds.
## Prerequisites
- Supabase CLI installed (`npx supabase --version`)
- Supabase project linked (`supabase link --project-ref <ref>`)
- Pro plan or higher for log drain support and extended log retention
- `@supabase/supabase-js` v2+ installed for application-level monitoring
## Instructions
### Step 1: Dashboard Reports and CLI Inspect Commands
Supabase Dashboard provides built-in reports under **Dashboard > Reports**:
| Report | What It Shows |
|--------|---------------|
| API Requests | Total requests, response times, error rates by endpoint |
| Database | Active connections, query counts, replication lag |
| Auth Usage | Signups, logins, provider breakdown, failed attempts |
| Storage | Bandwidth, object counts, bucket usage |
| Realtime | Active connections, messages per second, channel counts |
For deeper Postgres diagnostics, use the CLI inspect commands:
```bash
# Table sizes — find the largest tables
npx supabase inspect db table-sizes --linked
# Index usage — find unused indexes wasting space
npx supabase inspect db index-usage --linked
# Cache hit ratio — should be > 99% (below 95% means upgrade compute)
npx supabase inspect db cache-hit --linked
# Sequential scans — tables needing indexes
npx supabase inspect db seq-scans --linked
# Long-running queries — find stuck queries
npx supabase inspect db long-running-queries --linked
# Table index sizes — compare index vs table size
npx supabase inspect db table-index-sizes --linked
# Bloat — estimate wasted space from dead tuples
npx supabase inspect db bloat --linked
# Blocking queries — find lock contention
npx supabase inspect db blocking --linked
# Replication slots — check replication health
npx supabase inspect db replication-slots --linked
```
### Step 2: Query Analytics with pg_stat_statements and Log Drains
Enable `pg_stat_statements` for detailed query-level metrics:
```sql
-- Enable the extension (Dashboard > Database > Extensions, or SQL)
create extension if not exists pg_stat_statements;
-- Top 20 slowest queries by average execution time
select
substring(query, 1, 80) as query_preview,
calls,
round(mean_exec_time::numeric, 2) as avg_ms,
round(max_exec_time::numeric, 2) as max_ms,
round(total_exec_time::numeric, 2) as total_ms,
rows
from pg_stat_statements
where mean_exec_time > 50
order by mean_exec_time desc
limit 20;
-- Most-called queries (high call count may indicate N+1 problems)
select
substring(query, 1, 80) as query_preview,
calls,
round(mean_exec_time::numeric, 2) as avg_ms,
rows
from pg_stat_statements
order by calls desc
limit 20;
-- Real-time connection monitoring
select
state,
count(*) as connections,
max(age(now(), state_change))::text as longest_duration
from pg_stat_activity
where datname = current_database()
group by state
order by connections desc;
-- Reset stats after optimization (to measure improvement)
select pg_stat_statements_reset();
```
**Log drains** forward Supabase logs to external aggregation tools:
```bash
# Add a Datadog log drain
npx supabase log-drains add \
--name datadog-drain \
--type datadog \
--datadog-api-key "$DATADOG_API_KEY" \
--datadog-region us1 \
--linked
# Add a custom HTTP log drain (Logflare, Axiom, etc.)
npx supabase log-drains add \
--name custom-drain \
--type webhook \
--url "https://api.logflare.app/logs/supabase" \
--linked
# List active drains
npx supabase log-drains list --linked
# Remove a drain
npx supabase log-drains remove <drain-id> --linked
```
Log drain events include API requests, Auth events, Postgres logs, Storage operations, and Edge Function invocations.
### Step 3: Custom Metrics, Alerting, and Health Checks
**Custom metrics via Edge Functions** — emit structured events for business-level monitoring:
```typescript
// supabase/functions/collect-metrics/index.ts
import { createClient } from '@supabase/supabase-js';
import { serve } from 'https://deno.land/[email protected]/http/server.ts';
serve(async () => {
const supabase = createClient(
Deno.env.get('SUPABASE_URL')!,
Deno.env.get('SUPABASE_SERVICE_ROLE_KEY')!
);
// Collect quota-relevant metrics
const { count: userCount } = await supabase
.from('profiles')
.select('*', { count: 'exact', head: true });
const { count: storageObjects } = await supabase
.storage.from('uploads')
.list('', { limit: 1, offset: 0 })
.then(({ data }) => ({ count: data?.length ?? 0 }));
const { data: dbSize } = await supabase
.rpc('get_database_size');
const metrics = {
timestamp: new Date().toISOString(),
user_count: userCount,
db_size_mb: dbSize,
storage_objects: storageObjects,
};
// Store metrics for trend analysis
await supabase.from('app_metrics').insert(metrics);
// Alert on quota thresholds
const DB_LIMIT_MB = 8000; // 8GB Pro plan limit
if (dbSize > DB_LIMIT_MB * 0.85) {
console.warn(`[QUOTA_ALERT] Database at ${Math.round(dbSize / DB_LIMIT_MB * 100)}% capacity`);
// Send alert via webhook, email, or Slack
}
return new Response(JSON.stringify(metrics), {
headers: { 'Content-Type': 'application/json' },
});
});
```
Schedule it with a cron trigger in `supabase/config.toml`:
```toml
[functions.collect-metrics]
schedule = "*/15 * * * *" # Every 15 minutes
```
**Health check endpoint** for uptime monitoring (Uptime Robot, Pingdom, etc.):
```typescript
// supabase/functions/health/index.ts
import { createClient } from '@supabase/supabase-js';
import { serve } from 'https://deno.land/[email protected]/http/server.ts';
serve(async () => {
const supabase = createClient(
Deno.env.get('SUPABASE_URL')!,
Deno.env.get('SUPABASE_SERVICE_ROLE_KEY')!
);
const checks: Record<string, { status: string; latency_ms: number; detail?: string }> = {};
// Database check
const dbStart = Date.now();
const { error: dbErr } = await supabase.rpc('version');
checks.database = {
status: dbErr ? 'unhealthy' : 'healthy',
latency_ms: Date.now() - dbStart,
...(dbErr && { detail: dbErr.message }),
};
// Auth check
const authStart = Date.now();
const { error: authErr } = await supabase.auth.admin.listUsers({ perPage: 1 });
checks.auth = {
status: authErr ? 'unhealthy' : 'healthy',
latency_ms: Date.now() - authStart,
};
// Storage check
const storageStart = Date.now();
const { error: storageErr } = await supabase.storage.listBuckets();
checks.storage = {
status: storageErr ? 'unhealthy' : 'healthy',
latency_ms: Date.now() - storageStart,
};
const overall = Object.values(checks).every(c => c.status === 'healthy');
const statusCode = overall ? 200 : 503;
return new Response(
JSON.stringify({ status: overall ? 'healthy' : 'degraded', checks, timestamp: new Date().toISOString() }),
{ status: statusCode, headers: { 'Content-Type': 'application/json' } }
);
});
```
**Real-time connection monitoring** — track active Realtime connections:
```typescript
import { createClient } from '@supabase/supabase-js';
const supabase = createClient(
process.env.NEXT_PUBLIC_SUPABASE_URL!,
process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!
);
// Monitor channel state changes
const channel = supabase.channel('monitoring');
channel
.on('system', { event: '*' }, (payload) => {
console.log(`[REALTIME] System event:`, payload);
})
.subscribe((status) => {
console.log(`[REALTIME] Connection status: ${status}`);
if (status === 'CHANNEL_ERROR') {
console.error('[REALTIME] Connection lost — will auto-reconnect');
}
});
```
## Output
- Dashboard reports configured for API, database, and auth monitoring
- CLI inspect commands availableRelated in Data & Analytics
clawarr-suite
IncludedComprehensive management for self-hosted media stacks (Sonarr, Radarr, Lidarr, Readarr, Prowlarr, Bazarr, Overseerr, Plex, Tautulli, SABnzbd, Recyclarr, Unpackerr, Notifiarr, Maintainerr, Kometa, FlareSolverr). Deep library exploration, analytics, dashboard generation, content management, request handling, subtitle management, indexer control, download monitoring, quality profile sync, library cleanup automation, notification routing, collection/overlay management, and media tracker integration (Trakt, Letterboxd, Simkl).
querying-soql
IncludedSOQL query generation, optimization, and analysis with 100-point scoring. Use this skill when the user needs SOQL/SOSL authoring or optimization: natural-language-to-query generation, relationship queries, aggregates, query-plan analysis, and performance or safety improvements for Salesforce queries. TRIGGER when: user writes, optimizes, or debugs SOQL/SOSL queries, touches .soql files, or asks about relationship queries, aggregates, or query performance. DO NOT TRIGGER when: bulk data operations (use handling-sf-data), Apex DML logic (use generating-apex), or report/dashboard queries.
app-store-optimization
IncludedApp Store Optimization (ASO) toolkit for researching keywords, analyzing competitor rankings, generating metadata suggestions, and improving app visibility on Apple App Store and Google Play Store. Use when the user asks about ASO, app store rankings, app metadata, app titles and descriptions, app store listings, app visibility, or mobile app marketing on iOS or Android. Supports keyword research and scoring, competitor keyword analysis, metadata optimization, A/B test planning, launch checklists, and tracking ranking changes.
habit-flow
IncludedAI-powered atomic habit tracker with natural language logging, streak tracking, smart reminders, and coaching. Use for creating habits, logging completions naturally ("I meditated today"), viewing progress, and getting personalized coaching.
app-store-optimization
IncludedApp Store Optimization (ASO) toolkit for researching keywords, analyzing competitor rankings, generating metadata suggestions, and improving app visibility on Apple App Store and Google Play Store. Use when the user asks about ASO, app store rankings, app metadata, app titles and descriptions, app store listings, app visibility, or mobile app marketing on iOS or Android. Supports keyword research and scoring, competitor keyword analysis, metadata optimization, A/B test planning, launch checklists, and tracking ranking changes.
visualizing-data
IncludedBuilds dashboards, reports, and data-driven interfaces requiring charts, graphs, or visual analytics. Provides systematic framework for selecting appropriate visualizations based on data characteristics and analytical purpose. Includes 24+ visualization types organized by purpose (trends, comparisons, distributions, relationships, flows, hierarchies, geospatial), accessibility patterns (WCAG 2.1 AA compliance), colorblind-safe palettes, and performance optimization strategies. Use when creating visualizations, choosing chart types, displaying data graphically, or designing data interfaces.