Skip to main content

Services

This page covers the backend's external service integrations — the third-party providers and background workers wrapped by apps/backend/services/, sitting between the managers and the outside world. For the shared platform pieces underneath (Redis, rate limiting, logging, env vars), see Infrastructure.

Storage — AWS S3

All user-generated files (images, videos, audio, documents) are stored in AWS S3 via services/s3.service.js (AWS SDK v3).

Folder conventions

{folder}/user-{userId}/{subfolder}/item_{random}.{ext}
FolderContent
images/Chat message images
profiles/Profile pictures
posts/Post images
videos/Video files
thumbnails/Video thumbnails

Key operations

  • Stream upload — directly from a GraphQL Upload scalar
  • Buffer upload — for post-processed images
  • Signed URLs — for private/expiring file access
  • File existence check
  • Delete

Set DISABLE_S3=true to use mock responses in local development.


Email — AWS SES

Transactional emails are sent via services/email.service.js using AWS SES.

Built-in templates

MethodWhen sent
sendVerificationCodeEmail address verification
sendPasswordResetPassword reset link
sendWelcomeEmailNew account created

Custom templates

Pug templates in email-templates/ are supported via sendTemplateEmail. All emails can also be sent as raw HTML via sendEmail.

Env vars: AWS_REGION, AWS_ACCESS_KEY, AWS_SECRET_KEY, AWS_EMAIL, AWS_EMAIL_NAME.


SMS — Multi-provider

SMS authentication and OTP codes are sent via services/sms/sms.service.js, which uses an adapter pattern so the provider can be swapped without code changes.

Supported providers

ProviderDescription
Twilio (default)Standard SMS + Twilio Verify API for OTP
AWS SNSTransactional SMS via AWS
MessageBirdEuropean SMS provider

Switch at runtime by setting SMS_PROVIDER=twilio|aws-sns|messagebird. Code length: 6 digits, expiry window: configurable via VERIFIED_SMS_TIME_WAIT (default 5 minutes).


Image processing — Sharp

services/image-processing.service.js wraps Sharp for server-side image manipulation:

  • Resize with fit and position options
  • Convert HEIC/HEIF → JPEG (iOS photos)
  • Compress with configurable quality (default 90%)
  • Stream → Buffer conversion

Video processing — ffmpeg

services/video-processing.service.js handles video thumbnails:

  • Extract thumbnail at configurable seek time (default 00:00:02)
  • Configurable output size (default 600x? — proportional height)
  • Auto-upload thumbnail to S3

Push notifications

FCM (Android / Web)

services/firebase.service.js sends push notifications via Firebase Cloud Messaging. The notification worker processes jobs from the BullMQ queue.

APNs (iOS)

services/apns.service.js sends Apple Push Notifications for standard iOS alerts.

VoIP push (iOS calls)

services/voip-push.service.js delivers high-priority VoIP pushes via Apple's PushKit so incoming calls wake the iOS app immediately.

Notification worker

workers/notification.worker.js runs as a BullMQ worker consuming from the push-notifications Redis queue:

  • Concurrency: 10 jobs in parallel
  • Rate limit: 100 jobs/second
  • Queue: Redis-backed, survives restarts
  • Jobs are processed in the background — resolvers enqueue and return instantly

Analytics

services/analytics/analytics.service.js uses an adapter pattern to decouple event tracking from the storage backend.

Adapters

AdapterUse case
PostgreSQLDevelopment / low traffic
BigQueryProduction / high scale (partitioned by date)

Switch via ANALYTICS_DB_TYPE=postgres|bigquery.

Tracked events

TableEvents
user_eventsAny user action (post created, comment posted, etc.)
post_eventsPost views, likes, shares
admin_actionsAll admin mutations with IP and metadata
content_reportsReport submissions
engagement_metricsAggregated engagement counters

Data retention: configurable per table (cleanOldData(table, days)). Analytics failures are non-fatal — errors are caught and logged so they never break the main request.


LiveKit integration

Two services handle live streaming infrastructure:

  • services/livekit.service.js — creates rooms, generates access tokens (JWT), manages participants
  • services/livekit-monitor.service.js — monitors room health and active participant counts

Typing indicators

services/typing-indicator.service.js publishes typing status changes to the typingIndicator GraphQL subscription. Indicators auto-expire after a short timeout if the user stops typing without sending a setTypingStatus(false) event.


Password policy

services/password-policy.service.js enforces the platform password rules:

  • Minimum 8 characters
  • Must contain uppercase, lowercase, digit, and special character
  • Reuse prevention (last N passwords)

Environment variables summary

VariableService
AWS_REGION / ACCESS_KEY / SECRET_KEYS3, SES, SNS
AWS_BUCKET_NAMES3
AWS_EMAIL / AWS_EMAIL_NAMESES
SMS_PROVIDERSMS (twilio / aws-sns / messagebird)
TWILIO_ACCOUNT_SID / AUTH_TOKEN / PHONE_NUMBERTwilio
ANALYTICS_DB_TYPEAnalytics adapter
GCP_PROJECT_ID / BIGQUERY_DATASET_IDBigQuery analytics
LIVEKIT_URL / API_KEY / API_SECRETLiveKit