Skip to content
SeeItFlow
System Design · Trade-offs · ~20 min read

ChatGPT / AI Assistant — Trade-offs & Decisions

Every major decision in an AI assistant has a visible consequence in latency, reliability, quality, or cost — streaming versus batching, how much context to keep, which retries are safe. Each decision below follows Problem → Options → Decision → Why → Trade-offs; mechanics for each option live in Architecture Deep Dive, so this page focuses on what to choose and why.

Mangesh MandlikLast updated:
Decision 01

SSE vs WebSocket for Streaming

The assistant needs incremental token delivery, status events, and cancellation, but the client does not necessarily need full duplex real-time messaging.

Swipe to pan
ClientChat APILLM Gatewayprovider streamSSE Streamtoken/status/donePOST messagestream requestnormalized eventsevent: tokenevent: tool_callevent: done
SSE fits one-way token streaming especially well.

Option A — Server-Sent Events

Simple HTTP semantics, ordered server-to-client events, native browser support, straightforward load-balancer behavior, and a natural fit for "POST a message, then stream the answer." Cancellation and new user messages still travel as ordinary HTTP requests alongside the SSE channel — SSE only needs to carry the server→client direction.

Option B — WebSocket

Full duplex communication is more flexible for collaborative editing, voice, or bidirectional live control, but it adds connection lifecycle complexity, infrastructure tuning, and a broader protocol surface than a single chat turn needs.

Decision

The trade-off is that SSE is less general. If the roadmap includes synchronized cursors, live co-agents, or voice streaming, WebSocket may eventually become necessary for those specific surfaces. For a text-first assistant, SSE is the right default, and other HTTP-streaming alternatives can also serve narrower needs without moving the whole product to a socket model.

Decision 02

Long Context vs RAG

The system must ground answers in large external corpora and long conversations. This is not actually an either/or choice — long context and RAG solve overlapping but distinct problems.

Swipe to pan
Context Window Pressuresystemmemoryretrievalrecent turnsoverflownaive full-history replay keeps pushing rightFix: summarize older turns and cap each section instead of blindly truncating the tail.
Long context alone quickly turns into cost and noise problems for large corpora.
Swipe to pan
UserChat APIEmbed QueryVector DBtop-kRerankerPrompt Builderbest chunks onlyquestionembedsearchcandidatestop evidence
RAG narrows the prompt to the few chunks most relevant to the current turn.

Not a false binary

Use recent conversation turns directly, use retrieval for large external corpora that don't fit (or don't deserve to occupy) a full context window, and use summaries for older conversational state. Some tasks genuinely benefit from full-document context when the document fits the window and exact global reasoning across the whole document is required — RAG's chunk-based retrieval can actually hurt a task like "does this contract contain any clause about X anywhere" if the right clause gets chunked away from its surrounding context.

Option A — Long context only

Operationally simple: no embedding pipeline, no vector database, no retrieval tuning. But prompt size and cost rise with corpus size, and irrelevant history or document text often harms answer quality even when it technically fits.

Option B — RAG

Adds ingestion complexity but keeps prompts focused, cheaper, and easier to fit inside deterministic token budgets. It scales to document sets that dwarf any single context window, at the cost of retrieval-tuning risk.

Decision

Decision 03

Postgres + Vector Index vs Dedicated Vector DB

The system needs both durable metadata and semantic search. The real comparison is indexed vector search in relational storage versus dedicated vector infrastructure — not indexed search versus an unindexed scan.

Option A — Postgres with a vector extension/index

Operationally convenient: one backup story, one metadata home, fewer moving parts, and — with an appropriate vector index — genuinely acceptable ANN performance for many workloads, not just tiny ones.

Option B — Dedicated Vector DB

Better ANN performance ceiling, richer namespace/index tuning, and more predictable low-latency retrieval at very large scale or very high query concurrency. Purpose-built systems handle the largest embedding sets more gracefully.

Decision

The trade-off either way is operational: a dedicated vector store adds a system and a consistency-coordination problem between metadata rows and vector entries (see Vector/Metadata Index Consistency in Architecture Deep Dive); staying in Postgres longer avoids that but caps how far retrieval scale can grow before a migration becomes necessary.

Decision 04

Single Model vs Multi-Model Gateway

Should every request use the same flagship model, or should the platform route by task complexity and capability needs?

Swipe to pan
Chat APILLM Gatewayroute + retryFast Modelcheap / low latencyReasoning Modelhigh-capabilityCoding ModelspecializedFallbacksecondary providerrequestsimple chathard reasoningcode-heavyretry/failoverCircuit breakers open on unhealthy providers; router chooses the cheapest model likely to succeed.
The gateway is what makes multi-model routing practical rather than ad hoc.

Option A — Single model

Simple mental model, consistent quality behavior, and straightforward evaluation. But it often overpays for easy tasks, gives no resilience when that one provider or model class degrades, and locks the whole product to one vendor's safety and capability behavior.

Option B — Multi-model routing

Cheaper for simple tasks, more resilient under provider incidents, and able to exploit specialized coding or reasoning models where they excel — at the cost of routing policy, capability-compatibility checks, and ongoing evaluation discipline (see Routing Quality Evaluation in Architecture Deep Dive).

Decision

The trade-off is evaluation surface area, quality-consistency risk across model classes, provider lock-in avoidance versus multi-provider integration overhead, and the need to track safety-behavior differences between models routed to the same task.

Decision 05

Direct LLM Access vs Gateway

Application code can call providers directly, or it can depend on a central LLM Gateway that standardizes routing, retries, and policy.

Option A — Direct provider access

Fast to prototype, fewer hops, and reasonable for one team shipping one feature with one provider. A small product can legitimately call one provider through a thin adapter without needing a full gateway. But provider logic spreads across the codebase as more teams and features are added, and each one reimplements errors, rate limits, usage accounting, and failover independently.

Option B — Central gateway

Adds one internal hop but centralizes normalization, auth, policy, retries, circuit breakers, observability, and cost controls.

Decision

The trade-off is that the gateway becomes critical infrastructure and must itself be highly available — but that is usually preferable to duplicating fragile provider logic across every team once more than one depends on LLM access.

Decision 06

Full History vs Summaries vs Selective Retrieval

Long conversations need continuity, but sending the full transcript every turn quickly becomes too expensive and noisy.

Swipe to pan
UserConversation APIPostgresmessagesSummariesrolling stateLLM callPOST turnwrite/readsummaryassembled contextPersist turns durably, then use latest summary + recent messages for prompt construction.
Persist full history, but send a summary plus recent turns rather than replaying everything.

Option A — Full history in every prompt

Simple and intuitively safe, but token costs rise monotonically and context windows fill with stale details that no longer help the current question.

Option B — Rolling summaries + recent turns

Requires summarization logic and lifecycle management (see Conversation Summary Consistency), but keeps prompt size bounded while preserving important semantics from older turns.

Option C — Selective retrieval from conversation history

For very long conversations, targeted retrieval of specific older turns (treating conversation history itself as a small retrieval corpus) can surface a precise old detail that a summary might have compressed away, complementing recent turns and the rolling summary rather than replacing either.

Decision

The trade-off is summary quality and, if added, retrieval-tuning effort. Bad summaries can erase important nuance, so summary generation and refresh timing deserve real attention regardless of whether selective retrieval is layered on top.

Decision 07

Semantic Cache vs Traditional Cache

Chat inputs rarely repeat byte-for-byte, so exact-key caches have limited value for answer reuse — but semantic reuse needs real constraints, not just a similarity score.

Swipe to pan
Semantic cacheQueryEmbed + MatchCache Hitreuse answerCache Missbuild promptLLM Gatewayfresh inferencesimilar + freshlow similarityinferCache key includes semantic similarity, freshness, and context fingerprint — not just the raw user text.
Semantic similarity lets near-duplicate questions reuse prior answers only when freshness and context also match.

Option A — Traditional exact cache

Cheap, predictable, and easy to invalidate, but only catches identical prompts or near-identical normalized strings — that misses most real conversational repetition.

Option B — Semantic cache

Embeds queries and matches semantically similar requests, improving hit rates materially, but needs thresholds, freshness rules, and a full context fingerprint (scope, versions, personalization) to stay safe — semantic similarity alone is not sufficient justification for reuse (see Semantic Cache Safety in Architecture Deep Dive).

Decision

The trade-off is evaluation risk: exact caches are deterministic, while semantic caches need careful tuning and explicit bypass classes to avoid reusing an answer that is merely similar, not correct for this context (personalized, permission-sensitive, or action-oriented requests especially).

Decision 08

Sync vs Async Processing for Document Ingestion

When a user uploads a file, should the chat request wait for parsing and indexing, or should ingestion happen in the background?

Swipe to pan
ClientChat APIsigned uploadS3object storageAsync Queueingestion jobsWorkersparse/chunkChunk Metadataready for embeddingsrequest URLdirect uploadobject createddispatchwrite chunks
Async ingestion keeps the user-facing path fast and isolates heavy parsing work.

Option A — Synchronous ingestion

Simple UX because the document is immediately ready if it succeeds, but request latency becomes hostage to parser speed, OCR complexity, and embedding throughput for anything nontrivial.

Option B — Asynchronous ingestion

Fast upload acknowledgment, scalable workers, retries, and isolation from the chat path — at the cost of explicit status tracking so the user knows when retrieval is ready.

Decision

The trade-off is eventual readiness for the async path. Users may ask about a document before indexing completes, so the product needs clear processing states and graceful messaging regardless of which path a given upload took.

Decision 09

Stream Immediately vs Safety/Quality Buffer

Should raw provider output stream to the user the instant it arrives, or should the platform hold a short buffer to inspect content first?

The options

Fastest time-to-first-token — stream provider deltas essentially unmodified. Small moderation/validation buffer — hold a short window (a sentence, a few hundred milliseconds) so lightweight moderation or structural validation can run before release. Full-response validation before release — wait for the complete answer, validate it, then release — strongest control, weakest perceived latency.

Decision

Decision 10

Retry Same Provider vs Fail Over

When a provider call fails, should the gateway retry the same provider or fail over to a different one?

What the decision actually depends on

The failure class (see Provider Retry Semantics in Architecture Deep Dive) — a transient timeout before any output is a different situation than a failure after a tool call already executed. Whether output was already emitted to the user. Capability compatibility of the failover target (tools, context length, modality, structured-output support). Relative cost of the failover target. And whether any tool/side-effect state is already in flight, which failover cannot safely ignore.

Decision

Decision 11

Dense Retrieval vs Hybrid Retrieval

Should retrieval rely on dense semantic search alone, or combine it with lexical matching and metadata filters?

The comparison

Dense retrieval alone is simpler to operate and covers most conversational, semantically-phrased queries well. Hybrid retrieval (dense + lexical/BM25 + metadata filters + reranking) recovers exact-term precision — identifiers, error codes, names, rare terms — that dense-only search can miss, at the cost of running and maintaining an additional retrieval path.

Decision

Decision 12

Persist Every Token vs Periodic Checkpoint vs Final Only

How often should streamed assistant output actually be written to durable storage during generation?

The options

Persist every token — strongest recovery fidelity, but high write amplification for what is often a low-value granularity. Periodic checkpoint — buffer deltas and persist every N tokens or M milliseconds, giving strong recovery with bounded write load. Final only — simplest, but a crash mid-stream loses the entire partial output, and partial-stream recovery (see Partial Generation Recovery) becomes weak or impossible.

Decision

Decision 13

Stateless Agent Loop vs Durable Workflow

Not every agentic task needs the same durability guarantees — the right orchestration model depends on how long the task runs and how much it touches the outside world.

The options

An interactive, short agent loop (a few tool calls inside one chat turn) can reasonably use simpler in-process or state-store orchestration without durable checkpointing. A long-running or side-effect-heavy workflow (multi-step research, actions with real external consequences) needs durable checkpoints and resumability, so a crash doesn't force a restart that risks repeating a completed side effect.

Decision

Decision 14

Automatic Tool Execution vs User Confirmation

Should the model be allowed to execute a proposed tool call automatically, or does the action require explicit user approval first?

The decision axis

Risk and reversibility of the action class. Read-only actions (search, lookup, read a file) can generally run automatically since there's nothing to undo if the model chose poorly. Irreversible or consequential actions (send an email, create a financial transaction, delete data) should require explicit confirmation, because a wrong tool call there has a real-world cost that automatic execution can't take back.

Decision

Decision 15

Home-Region Conversation Writes vs Multi-Region Active Writes

Should each conversation have one home region that owns its writes, or should multiple regions accept writes for the same conversation?

The options

Home-region writes — each conversation has a write-authority region; stateless API and gateway components deploy globally and route conversation writes back to that region. Simpler ordering and failover reasoning; users far from the home region incur extra latency on writes. Multi-region active writes — multiple regions can accept writes for the same conversation concurrently, reducing local write latency but requiring real cross-region coordination to keep message ordering and turn state consistent.

Decision

Decision 16

Cache Coverage vs Freshness/Isolation

Maximizing cache hit rate is not the objective — correctness, permission isolation, and freshness bound how much can safely be cached.

The tension

Every additional request class made cache-eligible saves cost, but also expands the surface for a stale or cross-scope answer reaching the wrong user (see Semantic Cache Contamination in Failure & Scale Scenarios). Good candidates for caching are stable public factual transformations, deterministic low-personalization tasks, and expensive retrieval results under a safe, versioned scope. Poor candidates are personalized/memory-dependent responses, permission-sensitive private data, rapidly changing information, tool/action requests, and safety-sensitive decisions.

Decision

DecisionDefaultSwitch when
01 SSE vs WebSocketSSE for core chatRich bidirectional features such as synchronized cursors, live co-agents or voice
02 Long context vs RAGRAG for large or growing knowledge; recent turns plus summaries for continuityA document fits the window and needs whole-document reasoning
03 Postgres vs vector DBPostgres with a vector indexQuery volume, corpus size or latency outgrow the relational approach
04 Single model vs gatewayMulti-model gatewayOnly pays off if routing quality is measured, not just cost
05 Direct LLM vs gatewayGateway as routing, policy and observability needs growA single-team, single-provider product may delay it
06 History vs summariesSummaries plus recent turnsUsers often reference far-back details: add selective retrieval
07 Semantic vs traditional cacheSemantic cache for well-scoped, low-risk classes; exact caches elsewhereScope or risk of reuse is unclear: bypass
08 Sync vs async ingestionAsync ingestionSmall, bounded inline documents may be parsed synchronously
09 Stream vs bufferSmall moderation buffer where content safety mattersHighest-risk contexts justify full-response buffering
10 Retry vs fail overRetry only pre-output, pre-side-effect; fail over to a capability-compatible provider for outagesNever fail over mid-generation or blindly retry after a tool call
11 Dense vs hybrid retrievalDense only, measuredEvaluation shows a recall gap on exact-term queries
12 Stream persistencePeriodic checkpointsFinal-only for the lowest-stakes surfaces; per-token for audit requirements
13 Stateless vs durable agentEphemeral for short interactive stepsLong-running or side-effect-heavy work needs durable checkpointed workflows
14 Tool confirmationAutomatic for read-only toolsConfirmation for irreversible or high-consequence tools, set at declaration time
15 Region writesHome-region conversation writesMulti-region active writes only if the added consistency complexity is justified
16 Cache coverageExplicit allowlist by request classWhen in doubt, bypass the cache
Decision map — default choice and what flips it (summarised from the sixteen decisions above)