Full-stack tracing: Javascript observability with Pydantic Logfire
You've instrumented your Python backend with Logfire. You can see every FastAPI request, every database query, every external API call. But what happens before that request arrives? What did the user click? How long did they wait? What was the state of the application when things went wrong?
If your application has a JavaScript frontend—and statistically, it almost certainly does—there's a whole layer of your stack you're not seeing.
JavaScript is Everywhere
JavaScript powers 98.9% of websites on the client side. Even teams that are Python-first typically have JavaScript somewhere in their stack: a React dashboard, a Next.js marketing site, an admin panel built with Vue.
But it's not just browsers. JavaScript runs in:
- Node.js backends — over 4.6 million websites use Node.js server-side
- Edge functions — Cloudflare Workers, Vercel Edge Functions, Deno Deploy
- Desktop apps — Electron powers VS Code, Slack, Discord
- Mobile apps — React Native brings JavaScript to iOS and Android
And increasingly, these JavaScript layers serve as the interface to Python backends—the dominant choice for AI and machine learning workloads. Your React dashboard calls your PydanticAI-powered API. Your Next.js app talks to your FastAPI inference service. The user experience lives in JavaScript; the intelligence lives in Python.
For Python developers building modern AI-powered applications, JavaScript observability isn't optional—it's the missing piece of the puzzle.
Why Client-Side Observability Matters
Backend monitoring tells you what happened on your servers. But Google's research shows that 53% of mobile users abandon sites that take longer than 3 seconds to load, and case studies from companies like Vodafone and Lazada demonstrate that even modest performance improvements lead to measurable revenue gains. These problems often originate in the browser, not the backend.
See the Full User Journey
When a user reports "the app is slow," backend metrics might show normal response times. But what if the slowness is in the browser? Maybe a heavy JavaScript bundle is blocking rendering. Maybe a third-party script is competing for resources. Maybe the user's interaction triggers multiple redundant API calls.
With client-side observability, you see document load times, user interactions, network requests, and how they all connect to your backend traces.
Debug Issues You Couldn't See or Reason About Before
Here's a real example: we were receiving malformed payloads on a certain API endpoint. The backend validation was rejecting them, but we couldn't figure out why users were sending bad data. Only after instrumenting the client-side code path did we discover that a certain account was producing OTel traces with multiple root-level spans, resulting in a miscalculated payload that was far removed from the actual endpoint call. Detecting and fixing this issue would have been impossible without full-stack tracing.
Same API, Same Mental Model
If you already know Logfire in Python, you already know it in JavaScript:
# Python
logfire.info('User {user_id} logged in', user_id=123)
// JavaScript - same pattern
logfire.info('User {user_id} logged in', { user_id: 123 })
Message templates, log levels, spans—they all work the same way. The concepts you've learned transfer directly.
How It Works
Pydantic Logfire provides JavaScript SDKs for different runtime environments:
- Node.js — Full auto-instrumentation for HTTP, databases, and web frameworks
- Browser — Automatic tracing of fetch requests, page loads, and user interactions
- Cloudflare Workers — Edge function instrumentation
Auto-Instrumentation Does the Heavy Lifting
Just like logfire.instrument_fastapi() in Python, the JavaScript SDKs automatically instrument common libraries. Under the hood, Logfire uses OpenTelemetry's auto-instrumentation packages, which support 30+ libraries out of the box: web frameworks like Express, Fastify, Koa, Hapi, and NestJS; databases including PostgreSQL, MySQL, MongoDB, and Redis; plus GraphQL, gRPC, Kafka, and the AWS SDK. In the browser, every fetch() call and page load is captured automatically.
You focus on instrumenting your business logic. The plumbing is handled for you.
Browser Security: The Proxy Pattern
There's one important difference for browser instrumentation: you can't put your Logfire token in client-side code—it would be visible to anyone who opens DevTools. Instead, browser traces are sent to your own backend, which forwards them to Logfire with the token attached server-side.
It's a simple pattern, and the documentation walks through the setup for Express, Next.js, and other frameworks.
Distributed Tracing: The Complete Picture
This is where JavaScript observability really shines. When a user clicks a button in your React app, that click triggers a fetch() call. The browser SDK automatically attaches a trace context header to the request. Your Python backend receives that header and continues the same trace.
The result? A single trace that shows:
[Browser] Button click
└── [Browser] fetch /api/orders
└── [Python] POST /api/orders
└── [Python] SELECT * FROM orders
└── [Python] Redis cache lookup
You see the complete journey from user action to database query, with timing at every step. When something is slow, you know exactly where.
This is how distributed client-to-server traces from the nextjs example appears in the Logfire UI. You can interact with the example above by clicking on the spans.
Tips for Effective JavaScript Observability
Use Logfire During Development
Enable console output locally (console: true in the configuration) to see your traces in the terminal as you develop. It's a fast feedback loop that helps you understand what's being captured before you deploy. Keeping Logfire's live view on your second monitor is also a great way to spot issues early.
Let Auto-Instrumentation Handle the Basics
Don't manually instrument every HTTP call—that's already covered. Focus your manual spans on business-critical paths: checkout flows, authentication steps, data synchronization. Instrument the code where bugs would be most painful.
Track What Users Actually Experience
The metrics that matter are the ones users feel:
- Page load time — How long until the page is interactive?
- Interaction latency — How long between click and response?
- API timing from the browser — Not server processing time, but the full round-trip including network latency
Leverage Familiar Patterns
Everything you know from Python Logfire applies:
- Message templates extract attributes automatically
- Sensitive data scrubbing is built-in (passwords, tokens, API keys)
- Log levels work the same way (
trace,debug,info,warn,error)
Getting Started
The Logfire JavaScript SDK is open source and available on npm. Setup takes just a few minutes:
- Read the docs: logfire.pydantic.dev/docs/integrations/javascript
- Explore the examples: Express, Next.js, browser, and Cloudflare Workers examples in the GitHub repository
- Try it free: If you're not already using Logfire, sign up and get started
Full-stack observability means seeing your entire application—Python backend and JavaScript frontend—in one place, with traces that flow seamlessly between them. No more blind spots. No more guessing what happened in the browser.