- Strong isolation of protocol handling, domain logic, persistence, and delivery.
- Trait-based adapters for storage, queue, media processing, auth providers.
- Predictable performance through bounded queues + backpressure.
- Minimal unsafe Rust (only in well-reviewed media bindings layer if required).
- Observability built-in (tracing spans at boundaries).
[Client Apps] → HTTP API Layer → (AuthN/Z, Rate Limit, Validation) → Domain Services → Repos (DB + Cache) → Persistence (Postgres/SQLite) Federation Inbound (HTTP Inbox) → Signature Verification → Activity Router → Domain Services Federation Outbound Queue → Delivery Workers → Remote Inboxes Media Upload → Media Pipeline (Validation, Transform, Thumbnail, Blurhash, Store) → Storage Backend Schedulers (cron-like) → Tasks (Domain Subscription Fetch, Media Cleanup, Key Refresh) Telemetry Exporter → OTLP / Prometheus / Logs
- Interface Layer: HTTP (Axum or Actix-web) + JSON (Serde) + OpenAPI generation.
- Application Layer: Coordinators / Services orchestrating domain operations (PostingService, FederationService, ModerationService, AccountService, MediaService, PermissionSubscriptionService).
- Domain Layer: Pure logic objects + value types (Status, Visibility, InteractionPolicy, DomainPermissionSet, ActivityEnvelope) with invariants enforced in constructors.
- Infrastructure Layer: Repositories (trait) + Adapters (SQLx/Postgres, SQLx/Sqlite), StorageAdapter (LocalFs, S3), QueueAdapter (InMemory, Redis future), MediaProcessor, SignatureVerifier, OIDCClient, TOTPGenerator, MarkdownRenderer, HTMLSanitizer.
- Accounts & Auth
- Posting & Timelines
- Federation
- Moderation & Domain Permissions
- Media & Storage
- Configuration & Scheduling
- Observability
Each context exposes service traits; cross-context communication via domain events (in-process bus initial, pluggable later).
- core-domain: Entity/value types, errors, result enums, time utilities.
- core-infra: Shared adapter traits (Repository, Queue, Storage, Clock, Hasher, Signer).
- persistence-sqlx: Concrete impl for repositories (feature flags: postgres, sqlite).
- http-api: Route definitions, request/response DTOs, auth middleware, OpenAPI generator.
- federation: ActivityPub (serialize/deserialize, signature verify, activity router, delivery batching, dedupe store).
- media-pipeline: Upload validators, transcoding workers, blurhash, exif stripping.
- scheduling: Cron-like scheduler (time grid + durable last-run persistence).
- moderation: Reports, domain permissions engine, spam filter heuristics interface.
- auth: Local credential store, OIDC client, TOTP, OAuth2 provider (tokens, scopes), rate limiting + throttling.
- timeline: Feed assembly (home, public, hashtag) with pagination strategy + caching.
- config: Strong typed config loader (file + env + overrides) with validation.
- telemetry: Tracing, metrics, logging façades.
- cli: Admin commands (promote user, migrate, export/import, maintenance tasks).
- service-bin: Composition root main binary wiring crates + DI.
Client → /api/v1/statuses → Auth → PostingService.create() → (validate content policy, parse Markdown, sanitize) → MediaService link attachments → Repository(status).save() → FanoutPlan build → OutboundQueue.enqueue(deliveries) → TimelineAssembler.insert(home + possibly public) → Return hydrated Status DTO.
Remote POST inbox → SignatureVerifier.verify(request) → ActivityParser.deserialize(Create) → IdempotencyStore.check() → FederationService.handle_create(note) → Map to Status entity (visibility + local-only rules) → Save → Insert into timelines of permitted followers → Ack 2xx.
Scheduler tick → SubscriptionService.fetchAllDue() → For each: Downloader → Parser (CSV/JSON/plain) → Diff existing → Drafts->Update / Blocks/Allows apply (policy resolution algorithm: priority descending) → Persist changes + emit events (for logging/metrics) → Next run timestamp.
- SQL schema normalized: accounts, statuses, media_attachments, polls, poll_options, follows, follow_requests, favourites, announces, interaction_policies, reports, domain_permissions, domain_permission_subscriptions, drafts, emojis, oauth_apps, oauth_tokens, deliveries (outbound queue durable), delivery_attempts (history), config_snapshots.
- SQLite + Postgres via SQLx with feature gating; migrations stored as pure SQL; migration runner crate.
- Secondary indexes: statuses(account_id, created_at DESC), deliveries(state, next_attempt_at), domain_permissions(domain, type, priority), hashtag_status(status_id, hashtag_id), timeline(home_account_id, status_id).
- In-memory LRU (config target memory) for hot accounts, public keys, instance metadata, hashtags, recent statuses by id.
- Optionally integrate Redis for distributed cache (future). Trait: Cache<K,V> with get/set/ invalidate.
Initial: In-memory MPMC bounded channel (size configurable). Durable: deliveries table where workers poll (SELECT ... FOR UPDATE SKIP LOCKED) to allow horizontal scaling; memory channel acts as write-through cache of ready deliveries. Backpressure: When channel full, posting waits (bounded timeout) -> apply overflow policy (drop lowest priority or block). Metrics: queue_depth, delivery_latency, retry_count.
- Group recipients by shared inbox vs inbox.
- Serialize Activity JSON once per unique body variant.
- Batch sign (HTTP Signature) per target domain (reuse digest + date header).
- Enqueue Delivery records (pending, attempt=0, next_attempt_at=now).
- Worker picks pending sorted by next_attempt_at; concurrency = sender_multiplier * CPU.
- Retry policy: exponential backoff with jitter (2^n * base) capped; mark failed after N attempts (config) -> dead letter table.
- Idempotency: store delivered activity id + target domain hash to skip duplicate.
Stages: Accept (size/type sniff) → Store original temp → Transcode (if video/audio) → Generate thumbnails + blurhash → Strip EXIF → Persist variants → Commit metadata row (transaction) → Publish status referencing attachment IDs. Pool sizing deterministic; tasks instrumented with tracing spans.
- Strict Content Security Policy builder including dynamic storage origins.
- Signature verification enforces digest, date skew, key fetch caching with expiry + pinning.
- HTML sanitization allowlist minimal (links, emphasis, code blocks, lists, blockquote) no inline event handlers.
- Rate limiting pre-auth (IP) + post-auth (account) buckets.
- TOTP secrets stored encrypted at rest (libsodium or ring) with key rotation plan.
- All secrets loaded via env; config file redaction in logs.
Single layered loader: (Defaults → File (TOML/YAML) → Env var prefix GTS_ → CLI flags). Validation pass building typed Config struct; produce diff summary on startup. Hot-reload limited to non-critical fields (log level, exposure toggles) via signals.
Spans: http.request, db.query (sampling threshold), federation.outbound, federation.inbound, media.process, scheduler.run, subscription.fetch. Metrics: counter(deliveries_total{result}), gauge(queue_depth), histogram(request_duration_seconds{route}), gauge(db_pool_in_use), histogram(media_process_seconds), counter(spam_messages_filtered), gauge(active_sessions). Log correlation: request-id header propagate into spans.
Traits: Storage, Queue, MediaTranscoder, SpamFilter, AuthProvider, KeyFetcher, MarkdownRenderer, Sanitizer. Plugin architecture (Phase 2): dynamic library or Wasm sandbox for SpamFilter + MarkdownRenderer replacements.
- Export data (SQL dump + object storage copy) → Import translator tool (maps Go schema to Rust schema via staged adapters) → Validate counts (accounts, statuses, follows) ±0%. Tool crate: migrator-go2rust.
- Provide read-only compatibility mode: Rust server boot with Go DB schema + shadow write into new tables until cutover.
- Unit: domain invariants (visibility, interaction policy resolution, domain permission merging).
- Property: delivery dedupe, permission subscription diff algorithm.
- Integration: federation scenarios with test harness (embedded remote actor fixtures).
- Load: timeline read, posting fanout, media bursts.
- Security: fuzz signature parser, markdown sanitizer.
- Single Binary (SQLite + local storage) — small personal.
- Single Binary (Postgres + S3) — small community.
- Split: API + Workers (shared Postgres + S3) — medium scale.
- Scaled: API (N replicas), Workers (M replicas), Redis/Queue (future), CDN for media — larger deployment.
- Replace in-process queue with pluggable distributed (NATS or Redis streams) preserving Delivery trait contract.
- Add relay ingestion publisher crate.
- Introduce reputation scoring module feeding SpamFilter trait.
- Adopt Axum vs Actix: leaning Axum + tower for middleware simplicity, hyper alignment.
- Choose SQL migration tool (refinery vs sqlx migrate). Prefer sqlx migrate for fewer deps.
- Offload video transcoding to separate microservice? Start in-process, abstract early.
End Architecture.