My hobby dashboard blew through Vercel's free Speed Insights quota in 9 days. The email was polite: upgrade to Pro at $20/month, plus $10/month per project for continued analytics beyond 2,500 events. For a project that makes $0.
I already had the domain on Cloudflare for DNS. Turns out their Web Analytics product is free with no event cap and no per-project pricing. I ran both side by side for 30 days.
The numbers (30 days, same traffic ~41k page views)
| Metric | Vercel Speed Insights | Cloudflare Web Analytics |
|---|---|---|
| Cost at my traffic | $10/mo (over free 2.5k events) | $0 |
| Event cap | 2,500 free, then paywalled | None published |
| LCP / FID / CLS | Yes, per page | LCP via beacon, no per-page breakdown out of the box |
| Setup |
@vercel/speed-insights npm package |
One JS snippet or orange-cloud proxy |
| Data retention | 30 days (Pro) | 6 months |
| Cookie-less / GDPR-friendly | Yes | Yes |
The one real gap: Vercel gives you Core Web Vitals per page automatically. Cloudflare's dashboard is aggregated. So I closed that gap with a 40-line free Worker.
The missing piece: per-page vitals with a free Worker
A Worker on the free plan (100,000 requests/day) captures the web-vitals beacon and logs it with the page path. Add this snippet to your pages:
<script type="module">
import {onLCP, onFID, onCLS} from 'https://unpkg.com/web-vitals@3/dist/web-vitals.attribution.js?module';
const send = (m) => navigator.sendBeacon('https://vitals.example.workers.dev',
JSON.stringify({name: m.name, value: m.value, page: location.pathname}));
onLCP(send); onFID(send); onCLS(send);
</script>
Worker side (free tier, no KV needed for a hobby scale — just console.log into Workers Logpush or tail live):
export default {
async fetch(req) {
if (req.method !== 'POST') return new Response('ok');
const { name, value, page } = await req.json();
console.log(JSON.stringify({ name, value: Math.round(value), page, ts: Date.now() }));
return new Response('ok', { headers: { 'Access-Control-Allow-Origin': '*' } });
}
}
Now I have per-page LCP in my logs, for $0, on 100k requests/day I will never hit.
What I actually lost
Honest list, because "free is always better" is a lie people tell on the internet:
- Vercel's per-deployment vitals correlation (which deploy regressed LCP) — I now eyeball this weekly instead
- Zero-config setup. The Worker took me an afternoon, mostly CORS debugging
- The pretty chart. Cloudflare's dashboard is functional, not delightful
The uncomfortable conclusion
Vercel's paid analytics isn't selling data — it's selling not having to write 40 lines of JavaScript. For a funded team that's a fine trade. For a side project paying $10/month to look at its own Lighthouse scores, it's a subscription to a chart.
The $0 stack: Cloudflare Web Analytics (aggregate) + one free Worker (per-page) + a weekly console.log grep. Total monthly cost: $0. Total monthly time after setup: about 10 minutes.
Are you paying for analytics on a project that doesn't make money, or did I just talk myself out of a tool everyone else considers table stakes?
I sketched the Worker with an AI pair programmer (MonkeyCode, free tier): https://ly.cyberserval.tech/iIETXiF — the CORS preflight handler was its suggestion, and it was right on the first try.
Top comments (0)