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}
| Folder | Content |
|---|---|
images/ | Chat message images |
profiles/ | Profile pictures |
posts/ | Post images |
videos/ | Video files |
thumbnails/ | Video thumbnails |
Key operations
- Stream upload — directly from a GraphQL
Uploadscalar - 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
| Method | When sent |
|---|---|
sendVerificationCode | Email address verification |
sendPasswordReset | Password reset link |
sendWelcomeEmail | New 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
| Provider | Description |
|---|---|
| Twilio (default) | Standard SMS + Twilio Verify API for OTP |
| AWS SNS | Transactional SMS via AWS |
| MessageBird | European 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
fitandpositionoptions - 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
| Adapter | Use case |
|---|---|
| PostgreSQL | Development / low traffic |
| BigQuery | Production / high scale (partitioned by date) |
Switch via ANALYTICS_DB_TYPE=postgres|bigquery.
Tracked events
| Table | Events |
|---|---|
user_events | Any user action (post created, comment posted, etc.) |
post_events | Post views, likes, shares |
admin_actions | All admin mutations with IP and metadata |
content_reports | Report submissions |
engagement_metrics | Aggregated 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 participantsservices/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
| Variable | Service |
|---|---|
AWS_REGION / ACCESS_KEY / SECRET_KEY | S3, SES, SNS |
AWS_BUCKET_NAME | S3 |
AWS_EMAIL / AWS_EMAIL_NAME | SES |
SMS_PROVIDER | SMS (twilio / aws-sns / messagebird) |
TWILIO_ACCOUNT_SID / AUTH_TOKEN / PHONE_NUMBER | Twilio |
ANALYTICS_DB_TYPE | Analytics adapter |
GCP_PROJECT_ID / BIGQUERY_DATASET_ID | BigQuery analytics |
LIVEKIT_URL / API_KEY / API_SECRET | LiveKit |