Skip to content

Data, Privacy, and Retention

This page is for deployers, administrators, and security reviewers. It explains what SyncTV stores in PostgreSQL, Redis, runtime directories, logs, and backups, and what the default cleanup behavior is. It is not a legal compliance statement; actual compliance requirements depend on your jurisdiction, organization policy, and user terms.

LocationDataPersistence
PostgreSQLUsers, auth credentials, rooms, members, playlists, media, chat, notifications, audit logs, provider instances, user provider credentials, runtime settings, user preferencesMust be persistent
RedisRate limits, brute-force protection, token blacklist, OAuth2 state, WebAuthn challenges, cluster state, cache invalidation messagesUsually short-lived state; HA or persistence is recommended for multi-replica deployments
data_dirManagement socket, log files, HLS files, proxy slice cache files, and other runtime-owned outputDepends on enabled features
Logging platformRequests, errors, audit context, dependency failures, runtime stateRetained according to your logging policy
BackupsPostgreSQL dumps, secrets, config files, optional HLS or cache dataRetained according to your backup policy
DataExamplesRisk
User identifiersUsername, user ID, role, creation timeCan be linked to user activity
EmailUser email, email identity, notification recipientPII; only return to the user themselves or administrators
Authentication dataPassword credential, OPAQUE credential, WebAuthn credential, OAuth2 identity, email token, refresh token or blacklistHighly sensitive; should not enter logs
Provider credentialsAlist token, Emby API key, Bilibili cookie, remote provider JWT secretHighly sensitive; protected by security.credential_encryption_key
Room dataRoom name, members, permissions, playlists, media, playback state, invitations, review recordsBusiness data
Message dataChat, danmaku, notification contentMay contain user input and sensitive context
Audit dataActor, action, target, details, IP, User-AgentUseful for security investigations; may also contain personal data

User in client.proto contains email and should only be returned to the user themselves or administrators. Public contexts should use UserPublicView, which omits email and other PII.

User preferences are stored in user_preferences:

  • two_factor_enabled: user-level 2FA.
  • Notification fields: in-app and email notification preferences.
  • Provider default fields: default Alist, Emby, and Bilibili instance names.
  • settings JSONB: low-priority extension payload. Core preferences should use explicit database columns instead of being placed in JSON.

settings JSONB must not store secrets, tokens, passwords, cookies, or provider credentials.

Production should configure:

security:
credential_encryption_key_file: "/run/secrets/credential_encryption_key"

Requirements:

  • The key is a 64-character hex value.
  • The key must remain stable.
  • If the key is lost, encrypted provider credentials cannot be reliably recovered.
  • If the key leaks, rotate affected provider credentials and assess database backup exposure.

See Security and Secrets and Media Providers.

DataDefault behaviorConfiguration surface
Idle roomsSoft-deleted after room.room_ttl=172800 seconds. 0 disables automatic expiry.Runtime settings
Soft-deleted usersPermanently purged after 90 days by defaultInternal cleanup configuration
Soft-deleted roomsPermanently purged after 90 days by defaultInternal cleanup configuration
Expired email tokensDeleted 7 days after expiry by defaultInternal cleanup configuration
Expired provider credentialsDeleted after expires_at plus a 1-hour bufferInternal cleanup configuration
Read notificationsDeleted after 30 days by defaultInternal cleanup configuration
All notificationsMaximum retention is 90 days by defaultInternal cleanup configuration
Notification partitions6 months retained by defaultInternal partition management
Chat messagesAbsolute retention cap chat.message_retention_days=90 daysRuntime settings
Per-room chat countchat.max_messages_per_room=500; 0 means unlimitedRuntime settings
Chat partitions90 days retained by defaultInternal partition management
Audit log partitions12 months retained by defaultInternal partition management
Token blacklistExpired entries are cleaned in the backgroundInternal cleanup configuration

In multi-replica deployments, cleanup tasks are leader-gated to avoid duplicate cleanup work. Database maintenance runs at startup and periodically to clean email tokens, notifications, expired provider credentials, and old chat messages.

User deletion uses soft delete plus transactional resource cleanup:

  • The user row enters a deleted_at state.
  • OAuth2 mappings, email identities, email tokens, provider credentials, notifications, and related user data are cleaned as part of the deletion flow.
  • Room memberships are removed.
  • Chat messages may be anonymized or retained with necessary context according to user cleanup semantics.
  • Soft-deleted records are permanently purged after the retention window.

Room deletion also starts with soft delete and cleans room playlists, media, members, invitations, review records, playback state, and related resources. The room row is hard-deleted after the retention window.

Backups usually contain the most complete and sensitive data set.

Protect:

  • PostgreSQL backups.
  • jwt.secret, security.opaque_server_setup_secret, and security.credential_encryption_key.
  • Provider tokens, SMTP passwords, OAuth2 client secrets, and management tokens.
  • Helm Secrets, Compose .env, Kubernetes Secrets, and external secret-manager snapshots.

Deleting data from the live database does not remove it from historical backups. Define backup retention, encryption, and destruction procedures in your operational policy.

Logging guidance:

  • Use structured logs in production.
  • Do not log Authorization, Cookie, OAuth2 codes, email codes, passwords, provider tokens, or SMTP passwords.
  • Review config show, request headers, and error logs before sharing them in issues or internal tickets.

Metrics guidance:

  • Do not expose /metrics publicly.
  • Inject metrics bearer tokens or Basic passwords through secrets.
  • Metrics should describe capacity, error rates, connection counts, and latency. They should not contain user content.