Multi-tenant data isolation
Every tenant gets a strict ClientId partition key applied at every storage layer. Relational tables and our vector-search collections are keyed by ClientId with row-level and collection-level filters enforced at the query layer. The repository pattern rejects any query that omits ClientId at compile time via a static analyzer rule. Error-tracking projects, audit logs and blob containers all maintain the same partition discipline. Cross-tenant data is a structural impossibility, not a runtime check.
RAG retrieval pipeline
Ingest → chunk → embed → upsert: documents (PDF, DOCX, scraped HTML, FAQ pairs) are chunked at 200-500 tokens with 50-token overlap. Chunks embedded via our embedding model (1536-dimension vectors) and upserted into our vector-search index with metadata (ClientId, sourceUrl, chunkIndex). Query path: question embedded, top-K cosine-similarity search filtered by ClientId, ScoreThreshold 0.5 default. Retrieved chunks pass to the LLM with structured citation metadata so the response carries a Snippet per source. Reconciliation runs nightly as a Worker BackgroundService.
LLM provider abstraction
All LLM calls go through ILlmProvider - a thin abstraction over multiple language-model providers (a primary provider and an Enterprise-tier alternative for failover). Provider selection per tenant via configuration; failover routes automatically on rate-limit or 5xx. Token usage and cost report per-call in the response payload so that tenants can monitor spend in real time. Provider switching doesn't require customer-side migration - abstraction insulates application code.
Channel adapter pattern
Each channel (web widget, Telegram, WhatsApp Business, Instagram DM, email) implements IChannelAdapter - a common contract that translates channel-native message envelopes to a unified Conversation domain model. Adapter pattern lets the core query pipeline run channel-agnostic; per-channel formatting (Telegram inline keyboards, WhatsApp template messages) lives within the adapter. Adding a channel doesn't touch the query pipeline.
Streaming response pipeline
SSE-based streaming via /v1/query/ask-stream endpoint. First event is sources-early - emits citation metadata before LLM streaming starts (so widgets render "according to" hover-cards while the answer is still streaming). Subsequent events are token chunks; final event is done with aggregate metadata (total tokens, total cost, conversation log ID). Cuts perceived latency by ~70% vs synchronous response.
Sub-processor data flow
Customer query → TLS ingress → our API tier → embedding call to our model provider (US, SCC 2021/914) → vector search in our retrieval engine → LLM call to our language-model provider with retrieved chunks → response back through the API tier → SSE back to widget. Our error-monitoring provider receives sanitised error envelopes (PII scrubbed pre-emission). A transactional email provider handles transactional email (US, SCC 2021/914). A CDN / edge-security provider runs WAF and CDN edge globally. Sub-processors by category at /en/sub-processors/; the full list with vendor names is provided under NDA or in our Data Processing Agreement on request.
Deployment topology
A fully managed cloud platform runs the public API, the marketing site, the admin platform and the vertical hubs as separately scaled services. A managed relational database holds the relational store with daily backup and 24-hour point-in-time recovery. Our vector-search engine runs with per-tenant collections. A managed in-memory cache backs sessions and the rate-limit token bucket. Object storage holds document blobs. A CDN / edge-security provider sits in front for WAF / DDoS mitigation / CDN. CI workflows trigger production deploys on merge to the release branch.
Disaster recovery posture
RTO 4 hours, RPO 1 hour. Daily managed-database backups with 35-day retention; point-in-time recovery within the last 24 hours. Our vector-search engine is snapshotted nightly to object storage. Multi-region failover for high availability. DR runbook tested quarterly with simulated region failure. Status page at status.slatech.ai shows current component availability.
Eval pipeline
Answers built on retrieved content are scored by a second model call for factuality, with a flag when the answer states something the retrieved material does not support. Those scores are written per query and are visible to the customer who owns the site. There is no nightly per-vertical harness and no public scoreboard: a benchmark worth publishing needs a fixed question set and a rubric someone outside the company could re-run, and that work has not been done. See /en/eval/.
Observability stack
Error monitoring per backend service with PII scrubbing pre-emission. Synthetic transaction monitoring at 5-minute cadence. OpenTelemetry-instrumented spans for query pipeline timings. Per-tenant audit log exportable on the Enterprise tier. status.slatech.ai probes 12 production components and shows whether each is answering.