Claude-code-plugins posthog-cost-tuning
install
source · Clone the upstream repo
git clone https://github.com/jeremylongshore/claude-code-plugins-plus-skills
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/jeremylongshore/claude-code-plugins-plus-skills "$T" && mkdir -p ~/.claude/skills && cp -r "$T/plugins/saas-packs/posthog-pack/skills/posthog-cost-tuning" ~/.claude/skills/jeremylongshore-claude-code-plugins-posthog-cost-tuning && rm -rf "$T"
manifest:
plugins/saas-packs/posthog-pack/skills/posthog-cost-tuning/SKILL.mdsource content
PostHog Cost Tuning
Overview
PostHog Cloud pricing is event-based: 1M events/month free, then usage-based pricing beyond that. Session recordings, feature flag evaluations, and surveys each have their own free tiers. The biggest cost drivers are typically
$autocapture events, $pageview on high-traffic pages, and bot traffic. This skill covers specific techniques to reduce event volume without losing analytical value.
Prerequisites
- PostHog Cloud account with billing access
- Application instrumented with posthog-js
- Understanding of which events drive your analytics
PostHog Cloud Free Tiers (2025)
| Product | Free Tier | Overage |
|---|---|---|
| Product analytics | 1M events/month | ~$0.00031/event |
| Session recordings | 5K sessions/month | ~$0.04/session |
| Feature flags | 1M API requests/month | ~$0.0001/request |
| Surveys | 250 responses/month | ~$0.10/response |
Instructions
Step 1: Audit Current Event Volume
set -euo pipefail # See which events consume the most quota (last 30 days) curl "https://app.posthog.com/api/projects/$POSTHOG_PROJECT_ID/query/" \ -H "Authorization: Bearer $POSTHOG_PERSONAL_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "query": { "kind": "HogQLQuery", "query": "SELECT event, count() AS total FROM events WHERE timestamp > now() - interval 30 day GROUP BY event ORDER BY total DESC LIMIT 20" } }' | jq '.results[] | {event: .[0], count: .[1]}'
Step 2: Tune Autocapture
$autocapture is often the largest event volume. Restrict it to only useful interactions.
import posthog from 'posthog-js'; posthog.init(process.env.NEXT_PUBLIC_POSTHOG_KEY!, { api_host: 'https://us.i.posthog.com', autocapture: { // Only capture click and submit events (skip change, scroll, etc.) dom_event_allowlist: ['click', 'submit'], // Only capture meaningful elements element_allowlist: ['a', 'button', 'form', 'input[type=submit]'], // Only capture elements with this CSS class css_selector_allowlist: ['.track-click', '[data-track]'], // Skip internal/admin pages entirely url_ignorelist: ['/admin', '/health', '/api/internal', '/_next'], }, });
Step 3: Event Sampling with before_send
posthog.init(process.env.NEXT_PUBLIC_POSTHOG_KEY!, { api_host: 'https://us.i.posthog.com', before_send: (event) => { // 1. Always send business-critical events (no sampling) const critical = ['purchase', 'signup', 'subscription_started', 'subscription_canceled', 'error']; if (critical.includes(event.event)) return event; // 2. Drop bot traffic entirely const ua = navigator?.userAgent?.toLowerCase() || ''; if (/bot|crawler|spider|scrapy|headless|phantom|puppeteer/i.test(ua)) { return null; } // 3. Sample pageviews to 25% on high-traffic pages if (event.event === '$pageview') { const highTraffic = ['/', '/pricing', '/blog']; const url = event.properties?.$current_url || ''; if (highTraffic.some(p => url.endsWith(p))) { return Math.random() < 0.25 ? event : null; } return event; // Keep other pageviews at 100% } // 4. Sample autocapture to 20% if (event.event === '$autocapture') { return Math.random() < 0.2 ? event : null; } // 5. Sample pageleave to 50% if (event.event === '$pageleave') { return Math.random() < 0.5 ? event : null; } return event; // Keep all other events }, });
Step 4: Optimize Session Recording Costs
posthog.init(process.env.NEXT_PUBLIC_POSTHOG_KEY!, { api_host: 'https://us.i.posthog.com', session_recording: { // Record only 10% of sessions (saves 90% on recording costs) sampleRate: 0.1, // Don't record sessions shorter than 5 seconds (bounces) minimumDurationMilliseconds: 5000, // Record 100% of sessions with errors (most valuable for debugging) // This is configured in PostHog dashboard under Session Replay settings }, }); // Alternatively: disable recording for non-paying users posthog.init(process.env.NEXT_PUBLIC_POSTHOG_KEY!, { api_host: 'https://us.i.posthog.com', disable_session_recording: true, // Start disabled }); // Enable only for paying users if (user.plan !== 'free') { posthog.startSessionRecording(); }
Step 5: Monitor Usage and Set Alerts
set -euo pipefail # Check current month's event usage curl "https://app.posthog.com/api/projects/$POSTHOG_PROJECT_ID/query/" \ -H "Authorization: Bearer $POSTHOG_PERSONAL_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "query": { "kind": "HogQLQuery", "query": "SELECT count() AS total_events, uniq(distinct_id) AS unique_users, count() / dateDiff('"'"'day'"'"', toStartOfMonth(now()), now()) AS events_per_day FROM events WHERE timestamp > toStartOfMonth(now())" } }' | jq '.results[0] | { total_events: .[0], unique_users: .[1], avg_events_per_day: .[2], projected_monthly: (.[2] * 30), over_free_tier: (.[2] * 30 > 1000000) }'
// Automated cost monitoring async function checkPostHogBudget() { const result = await queryPostHog(` SELECT count() AS events_this_month FROM events WHERE timestamp > toStartOfMonth(now()) `); const eventsThisMonth = result.results[0][0]; const FREE_TIER = 1_000_000; const projectedMonthly = eventsThisMonth / (new Date().getDate() / 30); if (projectedMonthly > FREE_TIER * 0.8) { // Alert: approaching free tier limit await sendSlackAlert(`PostHog usage alert: ${Math.round(projectedMonthly / 1000)}K events projected this month (free tier: 1M)`); } }
Cost Reduction Estimates
| Technique | Typical Reduction | Impact on Analytics |
|---|---|---|
| Restrict autocapture elements | 40-60% | Low (keep meaningful clicks) |
| Filter bot traffic | 10-30% | None (bots are noise) |
| Sample $pageview on high-traffic | 20-40% | Low (trends still accurate) |
| Session recording at 10% | 90% on recordings | Medium (fewer sessions to review) |
| Disable $pageleave | 15-20% | Low (rarely analyzed) |
Error Handling
| Issue | Cause | Solution |
|---|---|---|
| Event volume spike | New feature without volume estimate | Forecast events before launch |
| Bill higher than expected | Bot traffic | Add bot filtering in |
| Missing critical events | Sampling too aggressive | Exclude revenue events from sampling |
| Free tier exceeded mid-month | Autocapture too broad | Restrict to elements only |
Output
- Autocapture restricted to meaningful interactions
- Event sampling reducing volume by 30-50%
- Bot traffic filtered
- Session recording sampled to 10%
- Budget monitoring with alerting