Skip to content

[POC] W3C/OpenTelemetry Trace Context Propagation#2163

Draft
grdsdev wants to merge 8 commits intomasterfrom
feat/trace-propagation
Draft

[POC] W3C/OpenTelemetry Trace Context Propagation#2163
grdsdev wants to merge 8 commits intomasterfrom
feat/trace-propagation

Conversation

@grdsdev
Copy link
Copy Markdown
Contributor

@grdsdev grdsdev commented Mar 11, 2026

⚠️ PROOF OF CONCEPT - DO NOT MERGE

This PR is a proof of concept to demonstrate W3C/OpenTelemetry trace context propagation in the Supabase JS SDK. It is not ready for production and should not be merged without further review, discussion, and refinement.

Summary

Implements automatic W3C/OpenTelemetry trace context propagation for HTTP requests to Supabase services (Auth, Storage, PostgREST, Functions). This enables end-to-end distributed tracing from client applications through Supabase services.

Key Design Principles:

  • Security First: Only propagates to Supabase domains (*.supabase.co, *.supabase.in, localhost)
  • OpenTelemetry Standard: Uses @opentelemetry/api as optional peer dependency
  • HTTP Only: Applies to HTTP requests, not WebSocket connections
  • Simple Configuration: Just two boolean flags
  • Zero Breaking Changes: Enabled by default with opt-out available

Implementation

New Package: @supabase/tracing

Created shared package in packages/shared/tracing/ with:

  • Trace context extraction from OpenTelemetry API (optional peer dependency)
  • W3C traceparent header parsing and validation
  • Target URL validation (Supabase domains only)
  • Graceful fallback when OpenTelemetry is not available

Core Changes: @supabase/supabase-js

Enhanced fetchWithAuth in packages/core/supabase-js/src/lib/fetch.ts to inject trace headers:

  • Centralized injection point for all HTTP libraries
  • Extracts trace context once per request
  • Validates target URLs before propagation
  • Respects sampling decisions
  • Never overwrites manually provided headers

Configuration

interface TracePropagationOptions {
  // Enable or disable trace propagation (default: true)
  enabled?: boolean

  // Respect upstream sampling decisions (default: true)
  respectSamplingDecision?: boolean
}

Usage Examples

Auto-Detection (Default)

import { createClient } from '@supabase/supabase-js'
import { trace } from '@opentelemetry/api'

const supabase = createClient('https://xyzcompany.supabase.co', 'public-anon-key')

const tracer = trace.getTracer('my-app')
await tracer.startActiveSpan('fetch-users', async (span) => {
  // This request automatically includes trace context headers
  const { data, error } = await supabase.from('users').select('*')
  span.end()
})

Disable Trace Propagation

const supabase = createClient('https://xyzcompany.supabase.co', 'public-anon-key', {
  tracePropagation: {
    enabled: false,
  },
})

Ignore Sampling Decisions

const supabase = createClient('https://xyzcompany.supabase.co', 'public-anon-key', {
  tracePropagation: {
    respectSamplingDecision: false, // Always propagate, ignore sampling
  },
})

Architecture

Centralized Injection Pattern:

User Code
  ↓
SupabaseClient
  ↓
Auth/Storage/PostgREST/Functions
  ↓
fetchWithAuth (SINGLE INJECTION POINT)
  ↓
HTTP Request with trace headers

Security Model:

  • Trace context only propagated to trusted Supabase domains
  • Automatic domain validation on every request
  • No data leakage to third-party domains

Testing

  • ✅ 58 unit tests in packages/shared/tracing/test/ (90%+ coverage)
  • ✅ 9 integration tests in packages/core/supabase-js/test/unit/fetch.test.ts
  • ✅ All tests passing
  • ✅ Manual verification with real OpenTelemetry SDK in test-tracing/

What Still Needs Work

  1. Documentation: Comprehensive docs for trace propagation configuration
  2. Performance Impact: Measure any performance overhead
  3. Security Review: Ensure no vulnerabilities introduced
  4. Community Feedback: Get input on API design
  5. Backend Support: Supabase services must accept and forward trace context
  6. Examples: Real-world examples with observability backends (Jaeger, Datadog, etc.)

References

Test Plan

# Build packages
npx nx build supabase-js

# Run tests
npx nx test tracing
npx nx test supabase-js

# Test with OpenTelemetry
cd test-tracing
npm install
node test-final.js

This is a POC for exploration and feedback. Do not merge without thorough review.

🤖 Generated with Claude Code

Implements automatic trace context propagation for distributed tracing
across all Supabase services. When enabled, the SDK automatically
attaches trace context headers (traceparent, tracestate, baggage) to
outgoing requests, enabling end-to-end request tracing from client
applications through Supabase services.

## Changes

### New Package: @supabase/trace-propagation
- Created shared package for trace context utilities
- Implements W3C Trace Context specification parsing
- Supports OpenTelemetry API integration with graceful fallback
- Provides URL target validation (string, RegExp, function matchers)
- Includes 63 unit tests with 85%+ coverage

### Enhanced: @supabase/supabase-js
- Updated fetchWithAuth to inject trace headers automatically
- Added TracePropagationOptions configuration API
- Updated SupabaseClient to support trace propagation
- Added Realtime WebSocket trace context via query parameters
- Added 9 integration tests for trace propagation scenarios
- Added comprehensive documentation to README

## Features

- **Auto-detection**: Automatically detects active trace context from
  OpenTelemetry API
- **Custom extractors**: Support for custom tracing systems
- **Security-first**: Only propagates to Supabase domains by default
- **Configurable targets**: Support for custom allowed domains
- **Sampling aware**: Respects upstream sampling decisions
- **Zero breaking changes**: Fully backward compatible

## Configuration Modes

- `auto` (default): Automatically detect and propagate trace context
- `off`: Disable trace propagation
- `manual`: Only propagate manually set headers

## Testing

- All builds pass (nx build supabase-js)
- All type checks pass
- 63 unit tests pass in trace-propagation package
- 95 unit tests pass in supabase-js (including new tests)
- 85%+ code coverage across all modules

Related: Linear SDK-578

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Mar 11, 2026

Important

Review skipped

Draft detected.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Central YAML (base), Organization UI (inherited)

Review profile: CHILL

Plan: Pro

Run ID: 2cfd0095-8111-44c8-b7d2-e794cb4a3ab1

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@pkg-pr-new
Copy link
Copy Markdown

pkg-pr-new bot commented Mar 11, 2026

Open in StackBlitz

@supabase/auth-js

npm i https://pkg.pr.new/@supabase/auth-js@2163

@supabase/functions-js

npm i https://pkg.pr.new/@supabase/functions-js@2163

@supabase/postgrest-js

npm i https://pkg.pr.new/@supabase/postgrest-js@2163

@supabase/realtime-js

npm i https://pkg.pr.new/@supabase/realtime-js@2163

@supabase/storage-js

npm i https://pkg.pr.new/@supabase/storage-js@2163

@supabase/supabase-js

npm i https://pkg.pr.new/@supabase/supabase-js@2163

commit: f200bf5

@mandarini mandarini added the do-not-merge Do not merge this PR. label Mar 11, 2026
const supabase = createClient('https://xyzcompany.supabase.co', 'public-anon-key', {
tracePropagation: {
mode: 'auto',
respectSamplingDecision: false, // Always propagate, ignore sampling
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should keep 👍

grdsdev and others added 6 commits March 12, 2026 05:54
Rename @supabase/trace-propagation to @supabase/tracing for consistency
with naming conventions across the codebase.

Changes:
- Rename packages/shared/trace-propagation to packages/shared/tracing
- Update package name from @supabase/trace-propagation to @supabase/tracing
- Update all imports in supabase-js package
- Update workspace configuration
- Rename test-trace-propagation to test-tracing

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Remove the customExtractor option from trace propagation configuration.
Users should rely on OpenTelemetry API for trace context extraction.

Changes:
- Remove customExtractor field from TracePropagationOptions interface
- Remove customExtractor parameter from extractTraceContext function
- Update all code that used customExtractor
- Remove custom extractor tests
- Update documentation in READMEs

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Simplify trace propagation API by changing from string-based mode
('auto' | 'off' | 'manual') to a simple boolean flag (enabled).

Changes:
- Replace TracePropagationMode type with boolean enabled field
- Remove mode field from TracePropagationOptions interface
- Add enabled?: boolean field (defaults to true)
- Update all code to check enabled flag instead of mode
- Remove 'manual' mode functionality
- Update tests to use boolean flag
- Update documentation in README

BREAKING CHANGE: The tracePropagation.mode option has been replaced with
tracePropagation.enabled. Update from { mode: 'auto' } to { enabled: true }
and from { mode: 'off' } to { enabled: false }.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Remove the ability for users to customize which domains receive trace
context headers. Trace propagation is now restricted to Supabase domains
only (*.supabase.co, *.supabase.in, localhost) for security.

Changes:
- Remove targets field from TracePropagationOptions interface
- Remove TracePropagationTarget import from types
- Update code to always use default Supabase domains
- Remove custom targets test case
- Update documentation to reflect fixed target domains

BREAKING CHANGE: The tracePropagation.targets option has been removed.
Trace context is now only propagated to Supabase domains for security.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Remove trace context propagation for Realtime WebSocket connections.
Trace propagation is now only applied to HTTP requests (REST API, Storage,
Functions, Auth) and not to WebSocket connections.

Changes:
- Remove trace context extraction from _initRealtimeClient
- Remove extractTraceContext import from SupabaseClient.ts
- Simplify Realtime client initialization

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants