Sofa

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:

ServerMobile AnalyticsMobile CrashesWeb App
SystemCustom reportingPostHogSentryNone
DefaultDisabledEnabledEnabledN/A
ToggleAdmin settingUser settingUser settingN/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
  }
}
FieldDescription
instanceIdA random UUID generated once per server instance. Not tied to any user or IP.
versionThe Sofa version running on your server.
archOS and CPU architecture (e.g. linux-x64, darwin-arm64).
usersUser count in a bucketed range: 1, 2-5, 6-10, 11-25, or 26+.
titlesTracked title count in a bucketed range: 0, 1-50, 51-200, 201-500, or 501+.
featuresWhich 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_URL environment 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.

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.

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 PII
  • beforeSend scrubs any remaining user/request data from JavaScript errors
  • Native crashes bypass beforeSend but 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:

On this page