Telemetry
How Sofa collects anonymous usage statistics.
Sofa includes optional, privacy-focused telemetry to help understand how the project is used. All systems can be disabled at any time.
What We Collect
Sofa has three separate telemetry systems depending on the platform:
| Server | Mobile Analytics | Mobile Crashes | Web App | |
|---|---|---|---|---|
| System | Custom reporting | PostHog | Sentry | None |
| Default | Disabled | Enabled | Enabled | N/A |
| Toggle | Admin setting | User setting | User setting | N/A |
The web app has zero analytics — no tracking scripts, no third-party services.
Server Telemetry
The self-hosted server can send a small, anonymous report once every 24 hours. It is disabled by default and must be explicitly enabled by an admin.
Enabling
Toggle telemetry in Settings → Admin → Telemetry.
What Gets Sent
A single JSON payload is sent to https://public-api.sofa.watch/v1/telemetry:
{
"instanceId": "a1b2c3d4-...",
"version": "1.2.0",
"arch": "linux-arm64",
"users": "2-5",
"titles": "51-200",
"features": {
"imageCache": true,
"oidc": false,
"scheduledBackups": true
}
}| Field | Description |
|---|---|
instanceId | A random UUID generated once per server instance. Not tied to any user or IP. |
version | The Sofa version running on your server. |
arch | OS and CPU architecture (e.g. linux-x64, darwin-arm64). |
users | User count in a bucketed range: 1, 2-5, 6-10, 11-25, or 26+. |
titles | Tracked title count in a bucketed range: 0, 1-50, 51-200, 201-500, or 501+. |
features | Which optional features are enabled — not how they're used, just whether they're on. |
User and title counts are bucketed into ranges so we can understand general adoption without knowing exact numbers.
What Is NOT Sent
- No personal data (names, emails, IP addresses)
- No watch history, ratings, or library contents
- No API keys or credentials
- No information about individual users
- No tracking of feature usage patterns — only whether features are enabled
How It Works
- Reports are sent at most once every 24 hours (cron job at 12:30 AM UTC)
- The instance ID is generated with
Bun.randomUUIDv7()on first use and stored locally in your database — it is never tied to your identity - If the report fails (network error, timeout), it is silently skipped — telemetry never blocks normal operation
- The
PUBLIC_API_URLenvironment variable controls where reports are sent (default:https://public-api.sofa.watch)
Mobile App Analytics
The native iOS and Android app uses PostHog for anonymous usage analytics. It is disabled by default and requires explicit user consent.
Consent Flow
Analytics starts disabled on both iOS and Android. You can enable it in Settings → Anonymous Usage Reporting and change your preference at any time.
What Gets Tracked
When analytics is enabled:
- Screen views — which screens you navigate to (e.g. "home", "search", "title detail"), without any content identifiers
- App lifecycle — when the app is opened or backgrounded
- Errors — uncaught JavaScript exceptions for crash reporting
What Is NOT Tracked
- No personal data (name, email, watch history, ratings)
- No media library contents or search queries
- No passwords or authentication tokens
- No user profiles are created in PostHog (
personProfiles: "never")
Identification
PostHog generates an anonymous, random device identifier. No advertising IDs, personal data, or other identifying information is sent.
Disabling
Toggle analytics off in Settings → Anonymous Usage Reporting. This immediately opts out of PostHog and stops all event collection.
Mobile App Crash Reporting
The native iOS and Android app uses Sentry for crash reporting, separate from the analytics toggle above. It is enabled by default and can be disabled in Settings.
Consent Flow
Crash reporting is enabled by default. You can disable it in Settings → Crash Reporting. Changes take effect after restarting the app (native crash handlers must be installed at startup).
What Gets Sent
When crash reporting is enabled:
- Crash reports — stack traces from JavaScript exceptions and native crashes (segfaults, OOM, ANR)
- Device info — OS version, device model, app version (no unique identifiers)
What Is NOT Sent
- No personal data (name, email, watch history, ratings)
- No screenshots or view hierarchies
- No performance traces or profiling data
- No session replays
- No navigation history or screen parameters
- No user identification — Sentry does not create user profiles
- No breadcrumbs beyond console errors
Privacy Measures
sendDefaultPii: false— prevents automatic collection of IP addresses and other PIIbeforeSendscrubs any remaining user/request data from JavaScript errors- Native crashes bypass
beforeSendbut contain only stack traces and device info — no PII - No advertising IDs or device fingerprinting
Disabling
Toggle crash reporting off in Settings → Crash Reporting. The change takes effect after restarting the app.
Source Code
All telemetry implementations are fully open source:
- Server telemetry:
packages/core/src/telemetry.ts - Mobile analytics:
apps/native/src/lib/posthog.ts - Crash reporting:
apps/native/src/lib/sentry.ts