<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd" xmlns:googleplay="http://www.google.com/schemas/play-podcasts/1.0"><channel><title><![CDATA[Shashank’s Substack]]></title><description><![CDATA[My personal Substack]]></description><link>https://programmingappliedai.substack.com</link><image><url>https://substackcdn.com/image/fetch/$s_!riGX!,w_256,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F58e132e8-cd28-4037-b0ef-feabb2b68221_144x144.png</url><title>Shashank’s Substack</title><link>https://programmingappliedai.substack.com</link></image><generator>Substack</generator><lastBuildDate>Thu, 05 Nov 2026 06:31:06 GMT</lastBuildDate><atom:link href="iframe.php?url=https%3A%2F%2Fprogrammingappliedai.substack.com%2Ffeed" rel="self" type="application/rss+xml"/><copyright><![CDATA[Shashank Mishra]]></copyright><language><![CDATA[en]]></language><webMaster><![CDATA[programmingappliedai@substack.com]]></webMaster><itunes:owner><itunes:email><![CDATA[programmingappliedai@substack.com]]></itunes:email><itunes:name><![CDATA[Shashank Mishra]]></itunes:name></itunes:owner><itunes:author><![CDATA[Shashank Mishra]]></itunes:author><googleplay:owner><![CDATA[programmingappliedai@substack.com]]></googleplay:owner><googleplay:email><![CDATA[programmingappliedai@substack.com]]></googleplay:email><googleplay:author><![CDATA[Shashank Mishra]]></googleplay:author><itunes:block><![CDATA[Yes]]></itunes:block><item><title><![CDATA[HLD: Real-Time RAG Pipeline — Documents Searchable Within Seconds]]></title><description><![CDATA[Design a Real-Time Retrieval-Augmented Generation (RAG) pipeline where documents are continuously ingested, processed, embedded, indexed, and made searchable within seconds of being uploaded or update]]></description><link>https://programmingappliedai.substack.com/p/hld-real-time-rag-pipeline-documents</link><guid isPermaLink="false">https://programmingappliedai.substack.com/p/hld-real-time-rag-pipeline-documents</guid><dc:creator><![CDATA[Shashank Mishra]]></dc:creator><pubDate>Sat, 24 Oct 2026 14:05:46 GMT</pubDate><enclosure url="iframe.php?url=https%3A%2F%2Fsubstackcdn.com%2Fimage%2Ffetch%2F%24s_%21riGX%21%2Cw_256%2Cc_limit%2Cf_auto%2Cq_auto%3Agood%2Cfl_progressive%3Asteep%2Fhttps%253A%252F%252Fsubstack-post-media.s3.amazonaws.com%252Fpublic%252Fimages%252F58e132e8-cd28-4037-b0ef-feabb2b68221_144x144.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>If you&#8217;re looking for paid 1:1 mentorship with a strong focus on Low-Level Design (LLD)&#8212;especially Multithreading and Concurrency&#8212;along with High-Level Design (HLD), Data Structures &amp; Algorithms (DSA), System Design, LLM/Generative AI systems, and research paper discussions, feel free to reach out.</p><p></p><p>The system should support millions of documents, concurrent ingestion and query workloads, incremental updates, document versioning, and reliable retrieval for LLM-powered applications.</p><h2>1. Functional Requirements (FR)</h2><ol><li><p>Users should be able to upload documents through APIs or connect external sources such as Google Drive, S3, and internal knowledge bases.</p></li><li><p>The system should extract text, clean and chunk documents, and generate embeddings asynchronously.</p></li><li><p>Newly uploaded or updated documents should become searchable within seconds under normal operating conditions.</p></li><li><p>Users should be able to perform semantic and keyword-based searches and retrieve relevant document chunks.</p></li><li><p>The system should support document updates, deletion, versioning, and re-indexing without disrupting query serving.</p></li></ol><h2>2. Non-Functional Requirements (NFR)</h2><ol><li><p><strong>Low indexing latency:</strong> Target a p95 time of less than 5 seconds from document ingestion to searchability for supported document sizes and normal workloads.</p></li><li><p><strong>Low query latency:</strong> Target p95 retrieval latency below 200 ms, excluding LLM generation and external reranking latency.</p></li><li><p><strong>Scalability:</strong> Support millions of documents and scale ingestion workers, embedding generation, indexing, and query serving independently.</p></li><li><p><strong>High availability:</strong> Target 99.9% availability for search APIs, with replicated storage and graceful degradation during component failures.</p></li><li><p><strong>Reliability and consistency:</strong> Prevent lost ingestion events, process retries safely, and ensure deleted or superseded document versions are not returned as valid results.</p></li></ol><p><em>Note:</em> These are proposed design targets, not guaranteed performance. Actual latency depends on document size, embedding model throughput, index configuration, and system load.</p><div><hr></div><h1>3. Capacity Estimation</h1><p>Let&#8217;s assume the following workload for our initial design.</p><ul><li><p>Documents ingested: 10 million per day.</p></li><li><p>Average document size: 100 KB.</p></li><li><p>Average chunks per document: 20.</p></li><li><p>Embedding dimensions: 768.</p></li><li><p>Embedding representation: 32-bit floating point.</p></li><li><p>Search requests: 10 million per day.</p></li></ul><h3>A. Document ingestion</h3><p>Average document ingestion rate:</p><p>10,000,000 / 86,400 &#8776; 116 documents/second.</p><p>Assuming a peak traffic multiplier of 5:</p><p>Peak ingestion rate &#8776; 580 documents/second.</p><h3>B. Embedding generation</h3><p>Total chunks generated daily:</p><p>10 million &#215; 20 = 200 million chunks/day.</p><p>Average embedding generation rate:</p><p>200 million / 86,400 &#8776; 2,315 embeddings/second.</p><p>Peak embedding rate at 5&#215; traffic:</p><p>Approximately 11,575 embeddings/second.</p><p>This is a significant workload. We need batched embedding generation, multiple workers, and potentially GPU-backed inference.</p><h3>C. Vector storage</h3><p>Each embedding occupies:</p><p>768 dimensions &#215; 4 bytes = 3,072 bytes.</p><p>For 200 million chunks:</p><p>200 million &#215; 3,072 bytes &#8776; 614 GB.</p><p>This is the raw vector storage generated per day, excluding metadata, index structures, replication, and storage overhead.</p><p>At this rate, raw vector storage grows by approximately 18.4 TB per month.</p><p><strong>Important design implication:</strong> We cannot rely on a single vector database instance. We need sharding, replication, index management, and potentially compression techniques such as product quantization.</p><h3>D. Query traffic</h3><p>10 million queries/day:</p><p>10 million / 86,400 &#8776; 116 queries/second.</p><p>At 5&#215; peak traffic:</p><p>Approximately 580 queries/second.</p><p>The retrieval system should scale independently of the ingestion pipeline because the two workloads have different resource requirements.</p><div><hr></div><h1>4. High-Level Architecture</h1><h2>Architecture diagram</h2><pre><code><code>                         DOCUMENT INGESTION
                                  |
                 +----------------+----------------+
                 |                                 |
           Upload API                         Source Connectors
                 |                           (S3, Drive, etc.)
                 +----------------+----------------+
                                  |
                          Ingestion Service
                                  |
                    +-------------+-------------+
                    |                           |
              Object Storage              Metadata DB
              (Original Files)          (Document Versions)
                    |
              Ingestion Event
                    |
                Kafka Topic
                    |
             Document Processing
                    |
           Text Extraction / OCR
                    |
             Cleaning and Parsing
                    |
               Chunking Service
                    |
             Chunk Generation
                    |
             Embedding Service
                    |
             Vector Index Writer
                    |
          +---------+----------+
          |                    |
     Vector Database       Keyword Index
       (ANN Search)        (BM25 / Lucene)
          |                    |
          +---------+----------+
                    |
             Search API Layer
                    |
             Query Processing
                    |
             Query Embedding
                    |
          +---------+----------+
          |                    |
     Vector Retrieval      Keyword Retrieval
          |                    |
          +---------+----------+
                    |
              Result Fusion
                    |
              Optional Reranker
                    |
             Top-K Relevant Chunks
                    |
             RAG / LLM Service
                    |
               Final Answer</code></code></pre><p>Supporting components:</p><pre><code><code>Redis:
- Cache frequent queries and document metadata.
- Store short-lived ingestion status.
- Cache query embeddings where appropriate.

Metadata Database:
- Store document ownership, versions, status, and indexing metadata.

Kafka:
- Buffer ingestion events.
- Decouple document processing, embedding generation, and indexing.

Object Storage:
- Store original documents and extracted document artifacts.

Observability:
- Track indexing latency, Kafka consumer lag, embedding failures,
  indexing failures, search latency, and document freshness.</code></code></pre><div><hr></div><h1>5. Microservices and Responsibilities</h1><h3>1. API Gateway</h3><p>Responsibilities:</p><ul><li><p>Authenticate users and validate tenant access.</p></li><li><p>Apply rate limits and request-size limits.</p></li><li><p>Route requests to ingestion and search services.</p></li><li><p>Enforce tenant-level quotas.</p></li></ul><h3>2. Ingestion Service</h3><p>Responsibilities:</p><ul><li><p>Accept document uploads and external-source events.</p></li><li><p>Generate document IDs and ingestion job IDs.</p></li><li><p>Store the original document in object storage.</p></li><li><p>Create metadata records and publish ingestion events.</p></li><li><p>Support idempotency to avoid duplicate ingestion jobs.</p></li></ul><h3>3. Document Processing Service</h3><p>Responsibilities:</p><ul><li><p>Extract text from PDFs, DOCX files, HTML, and other supported formats.</p></li><li><p>Run OCR for scanned documents where necessary.</p></li><li><p>Clean extracted text and preserve useful metadata.</p></li><li><p>Split documents into chunks suitable for retrieval.</p></li><li><p>Record processing failures and support retries.</p></li></ul><p>This service is CPU-intensive for many file formats, while OCR can require additional specialized compute.</p><h3>4. Embedding Service</h3><p>Responsibilities:</p><ul><li><p>Convert text chunks into vector embeddings.</p></li><li><p>Batch multiple chunks into embedding requests.</p></li><li><p>Support GPU-backed embedding models when appropriate.</p></li><li><p>Apply backpressure when inference capacity is exhausted.</p></li><li><p>Track the model version used to generate each embedding.</p></li></ul><h3>5. Indexing Service</h3><p>Responsibilities:</p><ul><li><p>Write vectors and metadata to the vector database.</p></li><li><p>Update the keyword index.</p></li><li><p>Maintain document-to-chunk mappings.</p></li><li><p>Handle retries and duplicate writes.</p></li><li><p>Publish an indexing-completion event after the required indexes are ready.</p></li></ul><h3>6. Metadata Service</h3><p>Responsibilities:</p><ul><li><p>Track document versions and ingestion states.</p></li><li><p>Maintain tenant and access-control metadata.</p></li><li><p>Track which chunks belong to each document version.</p></li><li><p>Coordinate updates, deletions, and re-indexing.</p></li></ul><h3>7. Search Service</h3><p>Responsibilities:</p><ul><li><p>Embed incoming search queries.</p></li><li><p>Execute vector similarity search.</p></li><li><p>Execute keyword retrieval through BM25.</p></li><li><p>Apply metadata filters and access-control constraints.</p></li><li><p>Merge results using a ranking strategy such as Reciprocal Rank Fusion (RRF).</p></li><li><p>Return relevant chunks and their metadata.</p></li></ul><h3>8. Reranking Service</h3><p>Responsibilities:</p><ul><li><p>Rerank the top candidate chunks using a cross-encoder or another ranking model.</p></li><li><p>Improve relevance before sending context to the LLM.</p></li><li><p>Operate within a configurable latency budget.</p></li></ul><p>Reranking is optional for some workloads because it adds computational cost and latency.</p><h3>9. RAG Orchestration Service</h3><p>Responsibilities:</p><ul><li><p>Assemble retrieved chunks into context.</p></li><li><p>Construct the prompt for the selected LLM.</p></li><li><p>Generate the final answer.</p></li><li><p>Return citations or references to source documents.</p></li><li><p>Track retrieval quality, token usage, and generation latency.</p></li></ul><div><hr></div><h1>6. API Design</h1><p>We&#8217;ll define APIs for document ingestion, ingestion status, search, updates, and deletion.</p><h2>API 1: Upload a document</h2><p><code>POST /v1/documents</code></p><p>Request:</p><pre><code><code>{
  "tenant_id": "tenant_123",
  "collection_id": "engineering_docs",
  "document_name": "kafka_architecture.pdf",
  "source_type": "upload",
  "content_type": "application/pdf",
  "content_url": "s3://documents/kafka_architecture.pdf",
  "metadata": {
    "department": "engineering",
    "visibility": "internal"
  }
}</code></code></pre><p>Response:</p><pre><code><code>{
  "document_id": "doc_123",
  "version": 1,
  "ingestion_job_id": "job_456",
  "status": "ACCEPTED"
}</code></code></pre><p><strong>Design considerations:</strong></p><ul><li><p>The actual file can be uploaded through a presigned object-storage URL to avoid routing large payloads through application servers.</p></li><li><p>The API creates a document record and an ingestion job.</p></li><li><p>The document ID remains stable across versions, while each version represents a specific document state.</p></li><li><p>The ingestion process is asynchronous; <code>ACCEPTED</code> does not mean the document is already searchable.</p></li><li><p>Use an idempotency key to prevent duplicate ingestion when clients retry requests.</p></li></ul><h2>API 2: Check ingestion status</h2><p><code>GET /v1/documents/{document_id}/status</code></p><p>Response:</p><pre><code><code>{
  "document_id": "doc_123",
  "version": 1,
  "status": "INDEXING",
  "stages": {
    "upload": "COMPLETED",
    "extraction": "COMPLETED",
    "chunking": "COMPLETED",
    "embedding": "COMPLETED",
    "indexing": "IN_PROGRESS"
  }
}</code></code></pre><p>Possible states:</p><pre><code><code>ACCEPTED
PROCESSING
CHUNKING
EMBEDDING
INDEXING
SEARCHABLE
FAILED
DELETING
DELETED</code></code></pre><p>The status API helps clients distinguish between successful ingestion and actual searchability.</p><h2>API 3: Search documents</h2><p><code>POST /v1/search</code></p><p>Request:</p><pre><code><code>{
  "tenant_id": "tenant_123",
  "collection_id": "engineering_docs",
  "query": "How does Kafka handle consumer failures?",
  "top_k": 10,
  "filters": {
    "department": "engineering"
  },
  "search_mode": "HYBRID"
}</code></code></pre><p>Response:</p><pre><code><code>{
  "query_id": "query_789",
  "results": [
    {
      "document_id": "doc_123",
      "document_version": 1,
      "chunk_id": "chunk_101",
      "text": "Kafka consumers can recover from failures by...",
      "score": 0.92,
      "source": {
        "document_name": "kafka_architecture.pdf",
        "page": 12
      }
    }
  ]
}</code></code></pre><p>Search modes:</p><ul><li><p><code>VECTOR</code>: Semantic similarity search.</p></li><li><p><code>KEYWORD</code>: Traditional lexical search using BM25.</p></li><li><p><code>HYBRID</code>: Combine semantic and keyword results.</p></li></ul><p>The service must enforce authorization independently of any tenant ID supplied in the request. Tenant identity should be derived from the authenticated principal and validated against the requested collection.</p><h2>API 4: Update a document</h2><p><code>PUT /v1/documents/{document_id}</code></p><p>Request:</p><pre><code><code>{
  "content_url": "s3://documents/kafka_architecture_v2.pdf",
  "metadata": {
    "department": "engineering",
    "visibility": "internal"
  }
}</code></code></pre><p>Response:</p><pre><code><code>{
  "document_id": "doc_123",
  "version": 2,
  "ingestion_job_id": "job_457",
  "status": "ACCEPTED"
}</code></code></pre><p>The new version is processed asynchronously. The system should track which version is active and prevent obsolete indexing jobs from replacing newer document content.</p><h2>API 5: Delete a document</h2><p><code>DELETE /v1/documents/{document_id}</code></p><p>Response:</p><pre><code><code>{
  "document_id": "doc_123",
  "status": "DELETION_ACCEPTED"
}</code></code></pre><p>Deletion should immediately mark the document as unavailable for new retrievals through an authoritative metadata or tombstone mechanism. Physical removal from vector and keyword indexes can happen asynchronously.</p><p>This distinction is important because distributed indexes may take time to propagate deletions.</p><div><hr></div><h1>7. Database Choices</h1><p>We should use different storage systems for different access patterns rather than forcing everything into one database.</p><h2>A. Object Storage &#8212; Original Documents</h2><p><strong>Choice:</strong> S3-compatible object storage.</p><p>Stores:</p><ul><li><p>Original documents.</p></li><li><p>Extracted text artifacts where useful.</p></li><li><p>Document-processing artifacts.</p></li><li><p>Archived versions when retention policies require them.</p></li></ul><p>Example object key:</p><pre><code><code>tenant_123/
  engineering_docs/
    doc_123/
      version_1/original.pdf
      version_2/original.pdf</code></code></pre><p>Why object storage?</p><ul><li><p>Low cost for large files.</p></li><li><p>High durability.</p></li><li><p>Easy integration with event-driven processing.</p></li><li><p>Independent scaling of document storage and compute.</p></li></ul><h2>B. Metadata Database</h2><p><strong>Choice:</strong> PostgreSQL for the initial design; a horizontally scalable relational or key-value store may be appropriate at larger scale.</p><p>Stores:</p><ul><li><p>Document ownership and tenant association.</p></li><li><p>Document version and lifecycle state.</p></li><li><p>Ingestion job status.</p></li><li><p>Chunk counts and indexing metadata.</p></li><li><p>Active version and deletion state.</p></li></ul><p>Example document record:</p><pre><code><code>{
  "document_id": "doc_123",
  "tenant_id": "tenant_123",
  "collection_id": "engineering_docs",
  "current_version": 2,
  "status": "SEARCHABLE",
  "created_at": "2026-10-24T10:00:00Z",
  "updated_at": "2026-10-24T10:05:00Z"
}</code></code></pre><p>Example version record:</p><pre><code><code>{
  "document_id": "doc_123",
  "version": 2,
  "object_key": "tenant_123/engineering_docs/doc_123/version_2/original.pdf",
  "embedding_model": "embedding-model-v3",
  "chunk_count": 20,
  "status": "SEARCHABLE",
  "created_at": "2026-10-24T10:05:00Z"
}</code></code></pre><h2>C. Vector Database</h2><p><strong>Choice:</strong> A distributed vector database such as Milvus, Qdrant, or Pinecone.</p><p>Stores:</p><ul><li><p>Chunk embeddings.</p></li><li><p>Chunk identifiers.</p></li><li><p>Document and version references.</p></li><li><p>Searchable metadata used for filtering.</p></li></ul><p>Example vector record:</p><pre><code><code>{
  "chunk_id": "chunk_101",
  "tenant_id": "tenant_123",
  "collection_id": "engineering_docs",
  "document_id": "doc_123",
  "document_version": 2,
  "chunk_index": 0,
  "embedding": [0.12, -0.04, 0.87],
  "metadata": {
    "department": "engineering",
    "page": 12
  }
}</code></code></pre><p>The embedding array is abbreviated here for readability; the actual vector would contain all 768 dimensions in our capacity example.</p><p>Use an approximate nearest-neighbor index such as HNSW or IVF-based indexing depending on memory constraints, update patterns, and recall requirements.</p><h2>D. Keyword Search Index</h2><p><strong>Choice:</strong> Elasticsearch or Apache Lucene-based infrastructure.</p><p>Stores:</p><ul><li><p>Extracted text.</p></li><li><p>Chunk identifiers.</p></li><li><p>Document and version references.</p></li><li><p>Filterable metadata.</p></li></ul><p>Why do we need keyword search alongside vectors?</p><p>Suppose a user asks:</p><blockquote><p>Find documentation for error code <code>KAFKA-1438</code>.</p></blockquote><p>Vector similarity alone may not reliably rank the exact identifier first. BM25-based retrieval is effective for exact terms, identifiers, and uncommon keywords.</p><p>Hybrid retrieval combines these strengths.</p><h2>E. Kafka</h2><p><strong>Choice:</strong> Apache Kafka.</p><p>Example topics:</p><pre><code><code>document-ingestion
document-extraction
document-chunking
embedding-generation
vector-indexing
keyword-indexing
document-deletion
document-dlq</code></code></pre><p>Kafka provides buffering, replay, and decoupling between processing stages.</p><p>Use the document ID or a suitable document-and-version key for partitioning when ordering related events matters. Avoid assuming that Kafka guarantees exactly-once effects in external databases; consumers and index writers still need idempotent processing.</p><h2>F. Redis</h2><p>Use Redis for:</p><ul><li><p>Short-lived ingestion status caching.</p></li><li><p>Query embedding caching.</p></li><li><p>Carefully scoped result caching.</p></li><li><p>Rate limiting.</p></li></ul><p>Do not use Redis as the authoritative source of document lifecycle state.</p><div><hr></div><h1>8. Real-Time Ingestion Workflow</h1><p>Let&#8217;s walk through what happens when a user uploads a new document.</p><h3>Step 1: Accept the document</h3><p>The client uploads a file and calls the ingestion API.</p><p>The ingestion service:</p><ol><li><p>Authenticates the caller.</p></li><li><p>Validates collection permissions.</p></li><li><p>Stores the document in object storage.</p></li><li><p>Creates a metadata record.</p></li><li><p>Publishes an ingestion event to Kafka.</p></li></ol><p>The API returns a job ID without waiting for the complete pipeline.</p><h3>Step 2: Extract and normalize text</h3><p>A processing worker consumes the event.</p><p>It extracts text from the file, performs OCR if necessary, normalizes the content, and preserves metadata such as page numbers and section headings.</p><p>Failed processing attempts are retried according to the error type and retry policy.</p><h3>Step 3: Chunk the document</h3><p>The chunking service divides the extracted text into smaller units.</p><p>For example:</p><pre><code><code>Document: Kafka Architecture

Chunk 1:
Kafka topics and partitions...

Chunk 2:
Consumer groups and offset management...

Chunk 3:
Replication and leader election...

Chunk 4:
Consumer failure handling...</code></code></pre><p>Chunk size should be chosen based on the embedding model, document structure, and retrieval quality.</p><p>Overlapping chunks can preserve context across boundaries, but excessive overlap increases storage and embedding costs.</p><h3>Step 4: Generate embeddings</h3><p>The embedding service processes chunks in batches.</p><pre><code><code>Chunk Text
    |
    v
Embedding Model
    |
    v
768-Dimensional Vector</code></code></pre><p>The service should:</p><ul><li><p>Batch requests to improve accelerator utilization.</p></li><li><p>Bound queue sizes to avoid unbounded memory growth.</p></li><li><p>Retry transient failures.</p></li><li><p>Record the model version.</p></li><li><p>Apply backpressure when the embedding service is overloaded.</p></li></ul><h3>Step 5: Update the indexes</h3><p>The indexing service writes the chunk vectors and metadata to the vector database.</p><p>It also indexes the extracted text in the keyword search engine.</p><p>These are separate writes, so they are not automatically atomic.</p><p>The system must track indexing progress and only declare a document fully searchable when the required retrieval paths are ready, or when an explicitly supported partial-search policy allows it.</p><h3>Step 6: Mark the document searchable</h3><p>After the required indexing operations succeed, the system updates the authoritative document version status to <code>SEARCHABLE</code>.</p><p>The status endpoint can now report successful ingestion.</p><p>The important distinction is:</p><p><strong>A document being stored does not mean it is searchable.</strong></p><p>Searchability is achieved only after the required processing and indexing steps have completed.</p><div><hr></div><h1>9. Search Query Workflow</h1><p>Consider this query:</p><blockquote><p>How does Kafka recover when a consumer crashes?</p></blockquote><p>The search flow is:</p><pre><code><code>Client
  |
  v
API Gateway
  |
  v
Search Service
  |
  v
Query Embedding
  |
  +-------------------------+
  |                         |
  v                         v
Vector Search           BM25 Search
  |                         |
  +------------+------------+
               |
               v
          Result Fusion
               |
               v
           Reranking
               |
               v
       Top-K Relevant Chunks
               |
               v
          RAG Service
               |
               v
          LLM Generation
               |
               v
         Answer + Citations</code></code></pre><h3>Why hybrid search?</h3><p>Vector search identifies semantically similar chunks even when the wording differs.</p><p>BM25 identifies exact terms and keyword matches.</p><p>We can combine rankings using Reciprocal Rank Fusion:</p><p>\[ RRF(d) = \sum_{r \in R} \frac{1}{k + rank_r(d)} \]</p><p>Where:</p><ul><li><p>\(d\) is a candidate document chunk.</p></li><li><p>\(R\) is the set of retrieval result lists.</p></li><li><p>\(rank_r(d)\) is the rank of that chunk in a result list.</p></li><li><p>\(k\) is a smoothing constant.</p></li></ul><p>The resulting candidates can be reranked before being passed to the LLM.</p><p>For latency-sensitive workloads, run vector and keyword retrieval in parallel rather than sequentially.</p><div><hr></div><h1>10. The Most Important Design Challenge: Searchability Within Seconds</h1><p>The hardest part of this system is not merely generating embeddings. It is ensuring that newly generated embeddings become visible to queries quickly.</p><p>Consider the following timeline:</p><pre><code><code>T+0 ms      Document uploaded
T+200 ms    Ingestion event published
T+800 ms    Text extraction completed
T+1200 ms   Chunking completed
T+2500 ms   Embeddings generated
T+3500 ms   Vector index updated
T+4200 ms   Keyword index updated
T+4500 ms   Document marked searchable</code></code></pre><p>These are illustrative timings, not measured performance results.</p><p>The total indexing latency is approximately:</p><p>\[ T_{index} = T_{queue} + T_{extract} + T_{chunk} + T_{embed} + T_{vector} + T_{keyword} + T_{publish} \]</p><p>Some stages can run in parallel, so the critical-path latency may be lower than the sum of all stage durations.</p><p>To meet the five-second target, we need to monitor the entire pipeline rather than optimizing only embedding generation.</p><h3>Optimization strategies</h3><p><strong>1. Minimize queueing delay</strong></p><ul><li><p>Scale Kafka consumers according to queue lag.</p></li><li><p>Keep sufficient embedding capacity for peak ingestion.</p></li><li><p>Use bounded queues and admission control.</p></li></ul><p><strong>2. Batch embeddings carefully</strong></p><ul><li><p>Larger batches improve throughput.</p></li><li><p>Excessively large batches increase waiting time.</p></li><li><p>Use adaptive batching based on traffic and latency objectives.</p></li></ul><p><strong>3. Optimize vector indexing</strong></p><ul><li><p>Use a vector database that supports incremental inserts.</p></li><li><p>Tune index parameters and write buffers.</p></li><li><p>Avoid expensive full-index rebuilds for every update.</p></li></ul><p><strong>4. Optimize keyword indexing</strong></p><ul><li><p>Use near-real-time index refreshes where supported.</p></li><li><p>Balance refresh frequency against indexing overhead.</p></li><li><p>Track refresh and visibility delays separately.</p></li></ul><p><strong>5. Measure freshness end to end</strong></p><p>Record timestamps for upload, extraction, embedding completion, index visibility, and searchability.</p><p>This helps identify whether the bottleneck is Kafka lag, GPU capacity, vector indexing, or keyword-index refresh.</p><div><hr></div><h1>11. Document Updates and Versioning</h1><p>Suppose version 1 of a document says:</p><pre><code><code>Kafka retains messages for 7 days.</code></code></pre><p>The document is updated, and version 2 says:</p><pre><code><code>Kafka retains messages for 14 days.</code></code></pre><p>We cannot allow stale chunks from version 1 to continue appearing as valid search results after version 2 becomes active.</p><h3>Recommended strategy: Versioned indexing</h3><ol><li><p>Create version 2 without immediately deleting version 1.</p></li><li><p>Extract, chunk, and embed version 2.</p></li><li><p>Index version 2 in the vector and keyword indexes.</p></li><li><p>Verify the required indexes are ready.</p></li><li><p>Atomically update the authoritative active-version pointer.</p></li><li><p>Ensure queries exclude obsolete versions.</p></li><li><p>Delete version 1&#8217;s indexed chunks asynchronously after the transition is safe.</p></li></ol><p>The authoritative active-version pointer can be stored in the metadata database, with suitable caching and invalidation.</p><h3>Why not delete version 1 first?</h3><p>If we delete version 1 before version 2 is searchable, the document temporarily disappears from search.</p><p>Versioned indexing enables a safer transition, although it requires additional storage and careful query filtering.</p><h3>Important race condition</h3><p>Suppose version 3 is submitted while version 2 is still processing.</p><p>If version 2 finishes after version 3, its worker must not overwrite the active version.</p><p>Use a monotonically increasing version number or fencing token and validate it when publishing indexing completion.</p><div><hr></div><h1>12. Handling Deletes and Stale Results</h1><p>Deletion is more complicated than removing a metadata record.</p><p>A document&#8217;s chunks may exist in multiple places:</p><ul><li><p>Vector database.</p></li><li><p>Keyword index.</p></li><li><p>Redis caches.</p></li><li><p>Replicas and index segments.</p></li><li><p>Pending Kafka messages.</p></li></ul><p>A robust deletion workflow should:</p><ol><li><p>Mark the document or version as deleted in authoritative metadata.</p></li><li><p>Prevent retrieval from returning it immediately by enforcing a deletion or visibility check.</p></li><li><p>Publish a deletion event.</p></li><li><p>Remove the chunks from the vector database and keyword index.</p></li><li><p>Invalidate relevant caches.</p></li><li><p>Retry failed deletions and reconcile inconsistent states.</p></li></ol><p><strong>Key principle:</strong> Logical deletion should take effect before asynchronous physical cleanup completes.</p><p>This avoids relying on the vector database&#8217;s deletion propagation timing to enforce document visibility.</p><p>For strict access-control or deletion requirements, validate returned candidates against authoritative visibility state, or use a strongly consistent visibility mechanism. This can add latency, so it should be designed deliberately.</p><div><hr></div><h1>13. Consistency Model</h1><p>We have three major data stores:</p><ul><li><p>Metadata database.</p></li><li><p>Vector database.</p></li><li><p>Keyword search index.</p></li></ul><p>They do not share a single atomic transaction.</p><p>Therefore, the system should use an asynchronous, version-aware consistency model.</p><h3>Recommended approach</h3><p><strong>Metadata database</strong></p><ul><li><p>Authoritative source for document lifecycle and active version.</p></li></ul><p><strong>Vector and keyword indexes</strong></p><ul><li><p>Eventually consistent projections of document content.</p></li><li><p>Updated asynchronously through retryable indexing jobs.</p></li></ul><p><strong>Kafka</strong></p><ul><li><p>Durable event transport for processing stages.</p></li><li><p>Supports replay and recovery.</p></li></ul><p><strong>Outbox pattern</strong></p><ul><li><p>If metadata changes and event publication must not be lost, write the metadata change and an outbox record in the same database transaction.</p></li><li><p>A separate publisher sends outbox records to Kafka and marks them as published.</p></li><li><p>Consumers must remain idempotent.</p></li></ul><h3>Example failure</h3><p>The indexing service writes vectors successfully but crashes before recording indexing completion.</p><p>On retry, the service should upsert the same chunk IDs rather than create duplicates.</p><p>A stable identifier could be generated from:</p><pre><code><code>tenant_id + document_id + version + chunk_index</code></code></pre><p>The vector index writer can use this identifier to make retries safe.</p><div><hr></div><h1>14. Scaling Strategy</h1><h3>Document processing</h3><p>Scale workers horizontally according to:</p><ul><li><p>Kafka consumer lag.</p></li><li><p>Average processing time.</p></li><li><p>CPU utilization.</p></li><li><p>Memory pressure.</p></li><li><p>OCR workload.</p></li></ul><h3>Embedding service</h3><p>Scale according to:</p><ul><li><p>Pending chunks.</p></li><li><p>Embeddings generated per second.</p></li><li><p>GPU utilization.</p></li><li><p>Batch size.</p></li><li><p>End-to-end embedding latency.</p></li></ul><p>GPU utilization alone is not sufficient. A GPU can be highly utilized while queueing delays violate freshness targets.</p><h3>Vector database</h3><p>Scale through:</p><ul><li><p>Sharding.</p></li><li><p>Replication.</p></li><li><p>Index partitioning.</p></li><li><p>Appropriate ANN index selection.</p></li><li><p>Vector compression where suitable.</p></li></ul><p>For 10 billion vectors, the index&#8217;s memory footprint and metadata overhead become major design considerations.</p><h3>Search service</h3><p>Scale stateless search workers horizontally.</p><p>Use bounded concurrency and request timeouts to prevent slow downstream vector queries from exhausting the service.</p><h3>Backpressure</h3><p>If embedding generation falls behind:</p><pre><code><code>Kafka lag increases
       |
       v
Embedding queue reaches threshold
       |
       v
Reduce ingestion admission rate
       |
       v
Scale workers or defer low-priority jobs
       |
       v
Protect query-serving capacity</code></code></pre><p>Ingestion should not consume unlimited resources at the expense of interactive search.</p><div><hr></div><h1>15. Failure Scenarios</h1><p>FailureHandling strategyDocument extraction failsRetry transient failures; send persistent failures to a DLQ.Embedding service becomes unavailableBuffer events in Kafka, apply backpressure, and resume after recovery.Vector database is unavailableRetry writes and preserve indexing state; keep affected versions unsearchable until the required index is ready.Keyword index is delayedTrack indexing completion separately and apply the configured searchability policy.Duplicate Kafka eventUse idempotent consumers and deterministic chunk IDs.Older version finishes after newer versionReject stale completion events using version checks or fencing tokens.Document is deleted while processingCheck deletion state before publishing the version as searchable.Redis becomes unavailableFall back to authoritative metadata and the underlying search systems, subject to capacity limits.Kafka consumer lag grows rapidlyScale consumers where possible, prioritize work, and apply admission control.A partial index update occursReconcile the vector and keyword indexes against authoritative metadata and retry missing operations.</p><div><hr></div><h1>16. Monitoring and Observability</h1><p>We should track the following metrics.</p><p><strong>Ingestion metrics</strong></p><ul><li><p>Documents accepted per second.</p></li><li><p>Document-processing failure rate.</p></li><li><p>Extraction and chunking latency.</p></li><li><p>Queue depth and Kafka consumer lag.</p></li></ul><p><strong>Embedding metrics</strong></p><ul><li><p>Embeddings generated per second.</p></li><li><p>Average batch size.</p></li><li><p>GPU utilization and memory usage.</p></li><li><p>Embedding failure rate and latency.</p></li></ul><p><strong>Indexing metrics</strong></p><ul><li><p>Vector-index write latency.</p></li><li><p>Keyword-index refresh latency.</p></li><li><p>Time from upload to searchability.</p></li><li><p>Number of partially indexed documents.</p></li><li><p>Version conflicts and stale-index count.</p></li></ul><p><strong>Search metrics</strong></p><ul><li><p>p50, p95, and p99 query latency.</p></li><li><p>Vector and keyword retrieval latency.</p></li><li><p>Cache hit ratio.</p></li><li><p>Recall@K and ranking quality.</p></li><li><p>Empty-result rate and stale-result rate.</p></li></ul><p><strong>RAG metrics</strong></p><ul><li><p>Time to first token and total generation latency.</p></li><li><p>Context relevance.</p></li><li><p>Answer groundedness.</p></li><li><p>Citation accuracy.</p></li><li><p>Cost per query.</p></li></ul><p>A particularly important metric is:</p><p>\[ \text{Indexing Freshness} = T_{\text{searchable}} - T_{\text{upload}} \]</p><p>Monitor its p50, p95, and p99 values. Averages alone can hide a backlog that affects a subset of documents.</p><div><hr></div><h1>17. Final Architecture Summary</h1><p>The architecture can be summarized as follows:</p><pre><code><code>INGESTION
API Gateway
    |
Ingestion Service
    |
Object Storage + Metadata DB
    |
Kafka
    |
Document Processing
    |
Chunking
    |
Embedding Service
    |
Vector Index + Keyword Index
    |
Document Marked Searchable


QUERY SERVING
Client
    |
API Gateway
    |
Search Service
    |
    +-------------------+
    |                   |
Vector Search       BM25 Search
    |                   |
    +---------+---------+
              |
         Result Fusion
              |
          Reranking
              |
        Relevant Chunks
              |
         RAG / LLM
              |
        Answer + Citations


LIFECYCLE MANAGEMENT
Metadata DB
    |
Versioning + Visibility
    |
Deletion Events
    |
Asynchronous Index Cleanup</code></code></pre><h3>Key design decisions</h3><ol><li><p><strong>Kafka decouples ingestion from processing</strong>, allowing workers to scale independently.</p></li><li><p><strong>Batched embedding generation</strong> improves throughput and accelerator utilization.</p></li><li><p><strong>Hybrid search</strong> combines semantic relevance with exact keyword matching.</p></li><li><p><strong>Versioned indexing</strong> enables safer updates without making existing content unavailable prematurely.</p></li><li><p><strong>Authoritative metadata and idempotent consumers</strong> make retries, deletions, and recovery manageable.</p></li><li><p><strong>Asynchronous index cleanup</strong> avoids requiring distributed transactions across the vector database and keyword index.</p></li><li><p><strong>End-to-end freshness monitoring</strong> helps ensure that documents become searchable within the target time.</p></li></ol><p>The central engineering challenge is balancing <strong>freshness, retrieval quality, and indexing cost</strong> while supporting continuous ingestion at scale.</p><div><hr></div><p>C. CONSISTENCY, VERSIONING, AND DELETION</p><p>1. CONSISTENCY PROBLEM</p><p>Our RAG pipeline uses multiple independent components:</p><p>- PostgreSQL: Stores document metadata and lifecycle state.</p><p>- Kafka: Carries asynchronous processing events.</p><p>- Vector Database: Stores embeddings and chunk metadata.</p><p>- Keyword Index: Stores searchable text and metadata.</p><p>- Redis: Caches metadata and search results.</p><p>- Object Storage: Stores original documents.</p><p>These systems do not participate in one shared atomic transaction.</p><p>Therefore, we must handle:</p><p>- Partial failures.</p><p>- Duplicate events.</p><p>- Stale indexing jobs.</p><p>- Concurrent document updates.</p><p>- Delayed index visibility.</p><p>- Deletions that have not propagated to every system.</p><p>2. DOCUMENT VERSIONING</p><p>Suppose a document initially contains:</p><p>Document: payment-retry-policy</p><p>Version: 1</p><p>Content:</p><p>Failed payments should be retried 3 times.</p><p>A user updates the document:</p><p>Document: payment-retry-policy</p><p>Version: 2</p><p>Content:</p><p>Failed payments should be retried 5 times.</p><p>We must ensure that the old version does not appear as the current document after version 2 becomes active.</p><p>Recommended approach: Versioned indexing.</p><p>Step 1:</p><p>Create version 2 in PostgreSQL.</p><p>Step 2:</p><p>Publish an indexing event to Kafka.</p><p>Step 3:</p><p>Extract the document text and generate chunks.</p><p>Step 4:</p><p>Generate embeddings for version 2.</p><p>Step 5:</p><p>Write version 2 chunks to the vector database.</p><p>Step 6:</p><p>Write version 2 chunks to the keyword index.</p><p>Step 7:</p><p>Verify that all required indexes are ready.</p><p>Step 8:</p><p>Atomically update the active-version pointer in PostgreSQL.</p><p>Step 9:</p><p>Ensure search requests exclude obsolete versions.</p><p>Step 10:</p><p>Delete version 1 chunks asynchronously after the transition is safe.</p><p>Why not delete version 1 immediately?</p><p>If we delete version 1 before version 2 is searchable, the document temporarily disappears from search.</p><p>Versioned indexing allows us to prepare the new version before switching to it.</p><p>3. HANDLING CONCURRENT UPDATES</p><p>Consider this scenario:</p><p>Version 2 is submitted at 10:00:00.</p><p>Version 3 is submitted at 10:00:01.</p><p>However, version 3 finishes indexing before version 2.</p><p>Without proper safeguards, version 2 could finish later and incorrectly overwrite version 3.</p><p>Solution:</p><p>- Assign monotonically increasing version numbers.</p><p>- Store the active version in PostgreSQL.</p><p>- Include the version number in every indexing event.</p><p>- Validate the version before activating it.</p><p>- Reject stale completion events.</p><p>- Use conditional updates or compare-and-set operations.</p><p>Example:</p><p>Document ID: doc_123</p><p>Active version: 3</p><p>A worker finishes indexing version 2.</p><p>Before activating version 2, the worker checks the current version.</p><p>Since version 3 is already active, version 2 cannot replace it.</p><p>Important:</p><p>The active-version update must be conditional and atomic.</p><p>A worker must never activate an older version simply because its processing finished later.</p><p>4. HANDLING DUPLICATE KAFKA EVENTS</p><p>Suppose a Kafka consumer processes an indexing event.</p><p>1. The consumer writes a vector successfully.</p><p>2. The consumer crashes before committing its Kafka offset.</p><p>3. Kafka delivers the same event again.</p><p>4. The consumer attempts to write the vector again.</p><p>Without idempotency, duplicate chunks may be created.</p><p>Solution: Use deterministic chunk IDs.</p><p>Example:</p><p>chunk_id = hash(</p><p>    tenant_id,</p><p>    document_id,</p><p>    document_version,</p><p>    chunk_index</p><p>)</p><p>The vector database uses an upsert operation with this identifier.</p><p>The keyword index uses the same stable logical identifier for the chunk.</p><p>Repeated processing updates the existing logical record rather than creating a duplicate.</p><p>For model migrations or embedding regeneration, include the index generation or embedding model version in the indexing identity where necessary.</p><p>This makes retries safe without requiring distributed transactions.</p><p>5. TRANSACTIONAL OUTBOX PATTERN</p><p>Consider the following failure:</p><p>1. PostgreSQL successfully creates a document record.</p><p>2. The application crashes before publishing the Kafka event.</p><p>3. The document exists in PostgreSQL but is never processed.</p><p>We can prevent this failure using the transactional outbox pattern.</p><p>Workflow:</p><p>1. Begin a PostgreSQL transaction.</p><p>2. Insert the document metadata.</p><p>3. Insert an event into the outbox table.</p><p>4. Commit the transaction.</p><p>5. An outbox publisher reads unpublished events.</p><p>6. The publisher sends events to Kafka.</p><p>7. The publisher marks successfully published events.</p><p>Both the metadata record and outbox event are committed in the same database transaction.</p><p>If the publisher crashes after publishing an event but before marking it as published, it may publish the event again.</p><p>Therefore, consumers must remain idempotent.</p><p>The outbox pattern prevents a committed metadata change from silently losing its corresponding event.</p><p>6. DELETION WORKFLOW</p><p>Suppose a user deletes document doc_123.</p><p>The document may still exist in:</p><p>- PostgreSQL.</p><p>- The vector database.</p><p>- The keyword index.</p><p>- Redis caches.</p><p>- Kafka queues.</p><p>- Object storage.</p><p>Deleting the document from PostgreSQL alone is insufficient.</p><p>Recommended workflow:</p><p>Step 1:</p><p>Mark the document as deleted or unavailable in authoritative metadata.</p><p>Step 2:</p><p>Prevent new searches from returning the document.</p><p>Step 3:</p><p>Publish a deletion event to Kafka.</p><p>Step 4:</p><p>Delete the document&#8217;s chunks from the vector database.</p><p>Step 5:</p><p>Delete the document&#8217;s chunks from the keyword index.</p><p>Step 6:</p><p>Invalidate relevant Redis cache entries.</p><p>Step 7:</p><p>Ensure pending indexing jobs cannot reactivate the deleted document.</p><p>Step 8:</p><p>Delete the original document from object storage according to the retention policy.</p><p>Step 9:</p><p>Retry failed cleanup operations.</p><p>Step 10:</p><p>Periodically reconcile the indexes against authoritative metadata.</p><p>Key principle:</p><p>Logical deletion must take effect before asynchronous physical cleanup completes.</p><p>This prevents a deleted document from appearing in search merely because index cleanup is still running.</p><p>7. DELETION RACE CONDITIONS</p><p>Consider this sequence:</p><p>1. Version 2 begins embedding generation.</p><p>2. A user deletes the document.</p><p>3. The deletion event is processed.</p><p>4. The vector database removes existing chunks.</p><p>5. The delayed embedding worker finishes.</p><p>6. The worker writes new vectors for the deleted document.</p><p>The document could reappear in the index.</p><p>To prevent this:</p><p>- Track document lifecycle state in PostgreSQL.</p><p>- Assign a version or lifecycle generation to each indexing job.</p><p>- Check deletion state before activating a version.</p><p>- Reject writes from stale generations.</p><p>- Enforce visibility checks during retrieval.</p><p>- Run reconciliation to detect unexpected indexed records.</p><p>A deletion tombstone should remain available long enough to prevent delayed events from resurrecting the document.</p><p>Do not rely exclusively on the order in which Kafka consumers process events across different topics.</p><p>8. HANDLING STALE SEARCH RESULTS</p><p>Suppose the vector database returns a chunk from version 1 while version 2 is active.</p><p>Before returning the result, the system must verify that the chunk belongs to an active and authorized document version.</p><p>Possible strategies:</p><p>Strategy A: Filter by active version.</p><p>Maintain version metadata and apply the active-version constraint during retrieval when supported.</p><p>Strategy B: Validate candidates against authoritative metadata.</p><p>Retrieve candidate IDs, then verify document visibility and active-version state before returning results.</p><p>Strategy C: Use versioned visibility metadata.</p><p>Maintain a visibility mechanism that can reject obsolete versions without requiring an expensive database lookup for every candidate.</p><p>Recommended approach:</p><p>Use index-level filtering where possible, combined with an authoritative visibility mechanism for correctness-sensitive cases.</p><p>A stale candidate must never reach the LLM context if the document is deleted or unauthorized.</p><p>Caching must not bypass these checks.</p><p>9. CONSISTENCY BETWEEN VECTOR AND KEYWORD INDEXES</p><p>Suppose version 2 has been written to the vector database, but the keyword index has not finished updating.</p><p>A hybrid search request may return inconsistent results.</p><p>There are two approaches.</p><p>Approach A: Wait for both indexes.</p><p>Mark a document searchable only after both the vector and keyword indexes are ready.</p><p>Advantages:</p><p>- Simpler search semantics.</p><p>- Predictable behavior.</p><p>- Easier debugging.</p><p>Disadvantages:</p><p>- The slower index determines the time to searchability.</p><p>Approach B: Partial searchability.</p><p>Track the readiness of each index independently.</p><p>For example:</p><p>vector_index_status = READY</p><p>keyword_index_status = INDEXING</p><p>The search service can temporarily use the vector index while the keyword index catches up.</p><p>Advantages:</p><p>- Potentially faster availability of new content.</p><p>Disadvantages:</p><p>- Search results may be incomplete.</p><p>- The system needs explicit partial-readiness semantics.</p><p>Recommended initial design:</p><p>Wait for both indexes before marking a document fully searchable.</p><p>If the five-second freshness target cannot be met, consider a recent-write buffer or an explicitly defined partial-searchability policy.</p><p>10. CONSISTENCY MODEL</p><p>PostgreSQL:</p><p>- Authoritative source for document lifecycle state.</p><p>- Stores active version and deletion state.</p><p>Kafka:</p><p>- Durable asynchronous event transport.</p><p>- Supports retries and replay.</p><p>Vector Database:</p><p>- Stores searchable embeddings.</p><p>- Updated asynchronously.</p><p>Keyword Index:</p><p>- Stores searchable text.</p><p>- Updated asynchronously.</p><p>Redis:</p><p>- Stores disposable cached data.</p><p>- Never serves as the sole authority for document visibility.</p><p>Object Storage:</p><p>- Stores original document content.</p><p>The overall architecture uses eventual consistency for index updates, with explicit visibility controls for document versions and deletions.</p><p>This means the indexes may temporarily contain stale records, but the search service must not expose records that are no longer valid.</p><p>11. RECONCILIATION</p><p>Even with retries and idempotency, inconsistencies can occur.</p><p>Examples:</p><p>- A vector exists without corresponding metadata.</p><p>- A document is active in PostgreSQL but missing from the keyword index.</p><p>- A deleted document still has indexed chunks.</p><p>- A document version is marked searchable even though an index write failed.</p><p>Run a periodic reconciliation job.</p><p>Workflow:</p><p>1. Read document metadata and active versions.</p><p>2. Compare expected chunks against vector-index records.</p><p>3. Compare expected chunks against keyword-index records.</p><p>4. Identify missing or stale chunks.</p><p>5. Retry failed indexing operations.</p><p>6. Remove orphaned records where appropriate.</p><p>7. Report persistent inconsistencies.</p><p>Reconciliation should be idempotent and safe to run repeatedly.</p><p>For large datasets, use incremental reconciliation and partitioned scans instead of repeatedly scanning every record.</p><p>12. FINAL SYSTEM DESIGN SUMMARY</p><p>Kafka ingestion and backpressure:</p><p>- Kafka buffers traffic spikes.</p><p>- Independent consumer groups scale processing stages.</p><p>- Bounded queues prevent memory exhaustion.</p><p>- Backpressure protects downstream services.</p><p>- Retries and dead-letter queues isolate failures.</p><p>- Idempotent processing prevents duplicate logical records.</p><p>Vector indexing and hybrid search:</p><p>- HNSW supports fast approximate nearest-neighbor search.</p><p>- IVF-PQ reduces memory requirements for large collections.</p><p>- BM25 handles exact keywords and identifiers.</p><p>- Vector search handles semantic similarity.</p><p>- Reciprocal Rank Fusion combines retrieval rankings.</p><p>- Reranking improves the ordering of candidate chunks.</p><p>- Sharding and replication support scale and availability.</p><p>Consistency, versioning, and deletion:</p><p>- PostgreSQL maintains authoritative lifecycle state.</p><p>- Versioned indexing supports safer document updates.</p><p>- Conditional updates prevent stale workers from activating old versions.</p><p>- The transactional outbox prevents lost events after metadata commits.</p><p>- Idempotent consumers make retries safe.</p><p>- Tombstones and visibility checks prevent deleted documents from reappearing.</p><p>- Reconciliation repairs inconsistencies across indexes.</p><p>The central design principle is:</p><p>Use asynchronous processing for scalability, idempotency for reliable retries, versioning for safe updates, and authoritative visibility checks for correctness.</p>]]></content:encoded></item><item><title><![CDATA[HLD: Design an Agent Memory System supporting short-term, long-term, episodic, and semantic memory. ]]></title><description><![CDATA[Explain memory extraction, summarization, retrieval, eviction policies, conflict resolution, and personalization.]]></description><link>https://programmingappliedai.substack.com/p/hld-design-an-agent-memory-system-196</link><guid isPermaLink="false">https://programmingappliedai.substack.com/p/hld-design-an-agent-memory-system-196</guid><dc:creator><![CDATA[Shashank Mishra]]></dc:creator><pubDate>Sat, 26 Sep 2026 06:20:00 GMT</pubDate><enclosure url="iframe.php?url=https%3A%2F%2Fsubstackcdn.com%2Fimage%2Ffetch%2F%24s_%21riGX%21%2Cw_256%2Cc_limit%2Cf_auto%2Cq_auto%3Agood%2Cfl_progressive%3Asteep%2Fhttps%253A%252F%252Fsubstack-post-media.s3.amazonaws.com%252Fpublic%252Fimages%252F58e132e8-cd28-4037-b0ef-feabb2b68221_144x144.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>If you&#8217;re looking for paid 1:1 mentorship with a strong focus on Low-Level Design (LLD)&#8212;especially Multithreading and Concurrency&#8212;along with High-Level Design (HLD), Data Structures &amp; Algorithms (DSA), System Design, LLM/Generative AI systems, and research paper discussions, feel free to reach out.</p><p>The mentorship is tailored for interview preparation, backend engineering, distributed systems, AI infrastructure, and building a strong systems-thinking foundation.</p><p>&#128233; Contact: <a href="iframe.php?url=mailto%3Aprogrammingappliedai%40gmail.com">programmingappliedai@gmail.com</a></p><p></p><p>Absolutely. Let&#8217;s design it as an <strong>interview-ready HLD</strong>, starting from requirements and APIs, then moving into architecture, storage, memory lifecycle, retrieval, conflict resolution, eviction, and personalization.</p><h2>1. Functional Requirements</h2><ol><li><p><strong>Store short-term memory</strong></p><ul><li><p>Maintain recent conversation/context for the active session.</p></li><li><p>Support fast reads/writes with low latency.</p></li><li><p>Automatically expire stale session context.</p></li></ul></li><li><p><strong>Extract long-term memories</strong></p><ul><li><p>Identify useful facts/preferences from conversations.</p></li><li><p>Example: <em>&#8220;I prefer Go for backend development.&#8221;</em></p></li><li><p>Store them independently of a single conversation.</p></li></ul></li><li><p><strong>Support episodic memory</strong></p><ul><li><p>Store important past events/interactions.</p></li><li><p>Example: <em>&#8220;User designed an AI Gateway on September 1.&#8221;</em></p></li><li><p>Preserve event time, context, and source conversation.</p></li></ul></li><li><p><strong>Support semantic memory</strong></p><ul><li><p>Store generalized knowledge/facts derived from multiple interactions.</p></li><li><p>Example: repeated conversations can establish that the user prefers system-design answers in a particular format.</p></li></ul></li><li><p><strong>Retrieve relevant memories</strong></p><ul><li><p>Given a new query, retrieve memories based on:</p><ul><li><p>semantic similarity</p></li><li><p>recency</p></li><li><p>importance</p></li><li><p>user/session scope</p></li><li><p>memory type</p></li></ul></li></ul></li><li><p><strong>Summarize and consolidate memories</strong></p><ul><li><p>Compress old conversations into summaries.</p></li><li><p>Merge multiple related memories.</p></li><li><p>Convert repeated episodic observations into semantic knowledge.</p></li></ul></li><li><p><strong>Update/delete memories</strong></p><ul><li><p>Allow memories to be corrected, deleted, or invalidated.</p></li><li><p>Support explicit user instructions such as &#8220;forget this.&#8221;</p></li></ul></li><li><p><strong>Resolve conflicting memories</strong></p><ul><li><p>Example:</p><ul><li><p>Old: <code>User prefers Java</code></p></li><li><p>New: <code>User now prefers Go</code></p></li></ul></li><li><p>Keep history while marking the latest valid preference.</p></li></ul></li><li><p><strong>Personalize responses</strong></p><ul><li><p>Provide the LLM with relevant long-term preferences, history, and context without sending the entire memory store.</p></li></ul></li></ol><div><hr></div><h1>2. Non-Functional Requirements</h1><ol><li><p><strong>Low retrieval latency</strong></p><ul><li><p>p95 memory retrieval &lt; 100 ms excluding LLM generation.</p></li></ul></li><li><p><strong>High availability</strong></p><ul><li><p>Target 99.99% availability for memory reads/writes.</p></li></ul></li><li><p><strong>Scalability</strong></p><ul><li><p>Support millions of users and billions of memories.</p></li><li><p>Horizontally scalable ingestion and retrieval.</p></li></ul></li><li><p><strong>Strong privacy/isolation</strong></p><ul><li><p>User memories must never leak across users/tenants.</p></li><li><p>Tenant/user ID must be part of authorization and storage partitioning.</p></li></ul></li><li><p><strong>Durability</strong></p><ul><li><p>Long-term, episodic, and semantic memories should survive service failures.</p></li><li><p>Target durable persistence with replication and backups.</p></li></ul></li><li><p><strong>Eventual consistency</strong></p><ul><li><p>Memory extraction and summarization can be asynchronous.</p></li><li><p>Recent conversation state should remain strongly consistent within a session.</p></li></ul></li><li><p><strong>Cost efficiency</strong></p><ul><li><p>Avoid sending unnecessary memories to LLMs.</p></li><li><p>Use tiered storage and summarization to reduce token/storage costs.</p></li></ul></li><li><p><strong>Explainability</strong></p><ul><li><p>Every memory should retain source/provenance information so we can answer:</p></li><li><p><em>&#8220;Why does the system think this about me?&#8221;</em></p></li></ul></li></ol><div><hr></div><h1>3. Memory Types</h1><p>We can model memory as four logical layers:</p><pre><code><code>                 Agent Memory
                      |
        +-------------+-------------+
        |             |             |
   Short-Term      Long-Term     Episodic
        |             |             |
   Conversation    Semantic      Past Events
      Context       Facts</code></code></pre><h3>Short-term memory</h3><p>Recent context:</p><pre><code><code>User:
"Let's design an Agent Memory System."

Assistant:
"Let's start with FR/NFR."

User:
"Add APIs too."</code></code></pre><p>Usually stored with TTL.</p><h3>Episodic memory</h3><p>Specific events:</p><pre><code><code>{
  "event": "User designed Agent Memory System",
  "timestamp": "2026-09-26",
  "context": "System design preparation"
}</code></code></pre><h3>Semantic memory</h3><p>Generalized knowledge:</p><pre><code><code>{
  "fact": "User prefers system design answers with FR, NFR,
            APIs, database choices and microservices architecture"
}</code></code></pre><h3>Long-term memory</h3><p>Long-term memory is the persistent layer containing useful information, primarily semantic and important episodic memories.</p><div><hr></div><h1>4. High-Level Architecture</h1><pre><code><code>                         +------------------+
                         |   Agent / LLM    |
                         +--------+---------+
                                  |
                                  v
                       +---------------------+
                       |   Memory Gateway     |
                       +----------+----------+
                                  |
               +------------------+------------------+
               |                  |                  |
               v                  v                  v
        Short-Term Store    Memory Retrieval    Memory Write
               |                  |                  |
               v                  v                  v
             Redis          Query Processor     Event Queue
                                  |                  |
                                  v                  v
                          +---------------+    +-------------+
                          | Vector Search |    | Extraction  |
                          +-------+-------+    |   Worker    |
                                  |            +------+------+
                                  |                   |
                                  v                   v
                           +-------------+      +-------------+
                           | Semantic DB |      | Summarizer  |
                           +-------------+      +-------------+
                                  |
                                  v
                           +-------------+
                           | Memory DB   |
                           +-------------+

                         Supporting Services
                                  |
          +-----------+-----------+-----------+-----------+
          |           |           |           |           |
       Ranking     Conflict    Eviction   Personalization
       Service    Resolver     Service       Service</code></code></pre><div><hr></div><h1>5. Microservices</h1><h3>1. Memory Gateway</h3><p>Main entry point.</p><p>Responsibilities:</p><pre><code><code>Authentication
Authorization
Read/write routing
Memory-type routing
Request validation</code></code></pre><div><hr></div><h3>2. Short-Term Memory Service</h3><p>Handles active conversation state.</p><pre><code><code>Conversation
    |
    v
Short-Term Memory Service
    |
    v
Redis</code></code></pre><p>Redis is suitable because we need:</p><ul><li><p>very low latency</p></li><li><p>TTL</p></li><li><p>session-oriented access</p></li><li><p>high write throughput</p></li></ul><div><hr></div><h3>3. Memory Extraction Service</h3><p>Consumes conversation events asynchronously.</p><pre><code><code>Conversation
     |
     v
Kafka
     |
     v
Memory Extraction Service
     |
     +----&gt; Semantic Memory
     |
     +----&gt; Episodic Memory</code></code></pre><p>The extractor can use an LLM or smaller classification/extraction model.</p><p>Example:</p><pre><code><code>"I hate dark mode. Always use light mode."

             |
             v

memory_type = PREFERENCE
key = theme
value = light
importance = 0.85</code></code></pre><div><hr></div><h3>4. Summarization Service</h3><p>Responsible for compression.</p><pre><code><code>Conversation History
        |
        v
Summarizer
        |
        +----&gt; Session Summary
        |
        +----&gt; Episodic Summary
        |
        +----&gt; Semantic Facts</code></code></pre><div><hr></div><h3>5. Memory Retrieval Service</h3><p>Responsible for finding memories relevant to the current request.</p><pre><code><code>Query
 |
 v
Query Embedding
 |
 v
Vector Search
 |
 +---- semantic similarity
 |
 +---- recency
 |
 +---- importance
 |
 +---- user scope
 |
 +---- memory type
 |
 v
Ranking
 |
 v
Top-K memories</code></code></pre><div><hr></div><h3>6. Conflict Resolution Service</h3><p>Handles contradictory memories.</p><p>Example:</p><pre><code><code>Memory 1:
User prefers Python

Memory 2:
User prefers Go</code></code></pre><p>Resolver considers:</p><pre><code><code>timestamp
confidence
source
explicitness
frequency
user correction</code></code></pre><p>and produces:</p><pre><code><code>Current:
User prefers Go

Previous:
User preferred Python</code></code></pre><p>We should generally <strong>avoid physically deleting historical evidence</strong> unless requested; instead mark old memories as superseded.</p><div><hr></div><h3>7. Eviction/Consolidation Service</h3><p>Responsible for:</p><pre><code><code>TTL expiration
Low-value memory removal
Memory compression
Duplicate merging
Episodic -&gt; semantic consolidation</code></code></pre><div><hr></div><h1>6. APIs</h1><h2>Store short-term memory</h2><pre><code><code>POST /v1/memory/short-term</code></code></pre><p>Request:</p><pre><code><code>{
  "user_id": "u123",
  "session_id": "s456",
  "messages": [
    {
      "role": "user",
      "content": "Let's design an agent memory system"
    }
  ]
}</code></code></pre><p>Response:</p><pre><code><code>{
  "session_id": "s456",
  "status": "stored"
}</code></code></pre><div><hr></div><h2>Get short-term memory</h2><pre><code><code>GET /v1/memory/short-term?user_id=u123&amp;session_id=s456</code></code></pre><p>Response:</p><pre><code><code>{
  "session_id": "s456",
  "messages": [
    {
      "role": "user",
      "content": "Let's design an agent memory system"
    }
  ],
  "summary": "User is designing an agent memory system."
}</code></code></pre><div><hr></div><h1>7. Store Long-Term Memory</h1><pre><code><code>POST /v1/memory/long-term</code></code></pre><p>Request:</p><pre><code><code>{
  "user_id": "u123",
  "type": "semantic",
  "key": "preferred_language",
  "value": "Go",
  "confidence": 0.94,
  "importance": 0.8,
  "source": {
    "conversation_id": "c123",
    "message_id": "m456"
  }
}</code></code></pre><p>Response:</p><pre><code><code>{
  "memory_id": "mem789",
  "status": "created"
}</code></code></pre><div><hr></div><h1>8. Retrieve Memory</h1><pre><code><code>POST /v1/memory/search</code></code></pre><p>Request:</p><pre><code><code>{
  "user_id": "u123",
  "query": "What programming language should I use?",
  "memory_types": [
    "semantic",
    "episodic"
  ],
  "top_k": 10
}</code></code></pre><p>Response:</p><pre><code><code>{
  "memories": [
    {
      "memory_id": "mem789",
      "type": "semantic",
      "content": "User prefers Go for backend development",
      "score": 0.93
    },
    {
      "memory_id": "mem321",
      "type": "episodic",
      "content": "User recently discussed a Go backend system",
      "score": 0.81
    }
  ]
}</code></code></pre><div><hr></div><h1>9. Delete Memory</h1><pre><code><code>DELETE /v1/memory/{memory_id}</code></code></pre><p>Response:</p><pre><code><code>{
  "memory_id": "mem789",
  "status": "deleted"
}</code></code></pre><p>For privacy-sensitive systems, deletion should also trigger deletion from:</p><pre><code><code>Primary DB
Vector DB
Caches
Search indexes
Derived summaries
Backups according to retention policy</code></code></pre><div><hr></div><h1>10. Update Memory</h1><pre><code><code>PATCH /v1/memory/{memory_id}</code></code></pre><p>Request:</p><pre><code><code>{
  "value": "Java",
  "reason": "User explicitly changed preference"
}</code></code></pre><p>Response:</p><pre><code><code>{
  "memory_id": "mem789",
  "status": "updated",
  "version": 3
}</code></code></pre><div><hr></div><h1>11. Database Choice</h1><p>I&#8217;d use multiple stores rather than forcing everything into one database.</p><pre><code><code>                    Memory System
                         |
        +----------------+----------------+
        |                |                |
       Redis          PostgreSQL       Vector DB
        |                |                |
   Short-term       Metadata/state     Embeddings</code></code></pre><h3>Redis</h3><p>For:</p><pre><code><code>Short-term memory
Session state
Hot memory cache
TTL</code></code></pre><div><hr></div><h3>PostgreSQL / DynamoDB</h3><p>For durable memory metadata:</p><pre><code><code>memory_id
user_id
memory_type
content
importance
confidence
created_at
updated_at
version
status
source</code></code></pre><p>For very large scale, DynamoDB/Cassandra can be used for horizontally scalable memory storage.</p><div><hr></div><h3>Vector Database</h3><p>Stores:</p><pre><code><code>embedding
memory_id
user_id
memory_type
metadata</code></code></pre><p>Possible technologies:</p><pre><code><code>Milvus
Qdrant
Weaviate
Pinecone
OpenSearch</code></code></pre><p>The critical point is that vector search must always be filtered by:</p><pre><code><code>tenant_id
+
user_id
+
memory permissions</code></code></pre><p>before returning results.</p><div><hr></div><h1>12. Memory Schema</h1><p>A logical memory object:</p><pre><code><code>{
  "memory_id": "mem123",
  "user_id": "u123",
  "tenant_id": "t1",

  "type": "semantic",

  "content": "User prefers Go for backend development",

  "embedding": "...",

  "importance": 0.85,
  "confidence": 0.94,

  "created_at": "2026-09-26T10:00:00Z",
  "updated_at": "2026-09-26T10:30:00Z",

  "last_accessed_at": "2026-09-26T11:00:00Z",

  "access_count": 12,

  "status": "active",

  "version": 3,

  "supersedes": null,

  "source": {
    "conversation_id": "c123",
    "message_id": "m456"
  }
}</code></code></pre><div><hr></div><h1>13. Memory Extraction Pipeline</h1><p>This is one of the most important parts of the design.</p><pre><code><code>User Message
     |
     v
Conversation Service
     |
     v
Kafka
     |
     v
Memory Extraction Worker
     |
     v
Candidate Memories
     |
     v
Importance + Confidence
     |
     v
Deduplication
     |
     v
Conflict Detection
     |
     v
Memory Store</code></code></pre><p>Example:</p><pre><code><code>User:
"I prefer Go for backend development and I'm preparing
for system design interviews."</code></code></pre><p>Extractor generates:</p><pre><code><code>[
  {
    "type": "semantic",
    "key": "preferred_backend_language",
    "value": "Go",
    "confidence": 0.95
  },
  {
    "type": "semantic",
    "key": "current_goal",
    "value": "system_design_interview_preparation",
    "confidence": 0.92
  }
]</code></code></pre><div><hr></div><h1>14. Should Every Message Become a Memory?</h1><p><strong>No.</strong></p><p>Otherwise memory becomes:</p><pre><code><code>Huge
Noisy
Expensive
Hard to retrieve</code></code></pre><p>We need a memory-worthiness classifier.</p><p>For each candidate:</p><pre><code><code>Memory Score =
Importance
&#215; Confidence
&#215; Future Utility
&#215; Persistence Probability</code></code></pre><p>Example:</p><pre><code><code>"What's the weather today?"
        -&gt; Don't store

"I prefer Go for backend systems."
        -&gt; Store

"I am designing a payment system today."
        -&gt; Episodic

"I prefer system design answers with APIs and DB choices."
        -&gt; Store as semantic preference</code></code></pre><div><hr></div><h1>15. Retrieval Strategy</h1><p>Pure vector similarity isn&#8217;t enough.</p><p>Suppose the query is:</p><blockquote><p>&#8220;Design another system for me.&#8221;</p></blockquote><p>Vector search might return hundreds of semantically similar memories.</p><p>Instead calculate:</p><pre><code><code>FinalScore =
    &#945; * SemanticSimilarity
  + &#946; * Recency
  + &#947; * Importance
  + &#948; * AccessFrequency
  + &#949; * Confidence</code></code></pre><p>For example:</p><pre><code><code>semantic similarity = 0.82
importance           = 0.90
recency              = 0.70
confidence           = 0.95</code></code></pre><p>Then rank memories.</p><div><hr></div><h1>16. Hybrid Retrieval</h1><p>Use multiple retrieval strategies:</p><pre><code><code>                   Query
                     |
        +------------+------------+
        |            |            |
     Vector       Keyword       Metadata
     Search       Search         Filter
        |            |            |
        +------------+------------+
                     |
                     v
                  Fusion
                     |
                     v
                  Reranker
                     |
                     v
                   Top-K</code></code></pre><p>This handles queries where semantic similarity alone isn&#8217;t enough.</p><div><hr></div><h1>17. Memory Summarization</h1><p>Suppose a conversation has:</p><pre><code><code>500 messages
50,000 tokens</code></code></pre><p>We shouldn&#8217;t continuously retrieve all of them.</p><p>Use hierarchical summarization:</p><pre><code><code>Messages
   |
   v
Message chunks
   |
   v
Chunk summaries
   |
   v
Conversation summary
   |
   v
Long-term facts</code></code></pre><p>Example:</p><pre><code><code>500 messages

       &#8595;

10 chunk summaries

       &#8595;

1 conversation summary

       &#8595;

5 semantic memories</code></code></pre><p>This dramatically reduces context size.</p><div><hr></div><h1>18. Episodic &#8594; Semantic Consolidation</h1><p>This is an important distinction.</p><p>Suppose we have:</p><pre><code><code>Episode 1:
User asked for Go system design.

Episode 2:
User asked for Go concurrency design.

Episode 3:
User chose Go for backend examples.</code></code></pre><p>The system can infer:</p><pre><code><code>Semantic Memory:
User frequently prefers Go for backend/system-design examples.</code></code></pre><p>Pipeline:</p><pre><code><code>Episodic Memories
       |
       v
Pattern Detection
       |
       v
LLM / Consolidation Model
       |
       v
Semantic Memory</code></code></pre><div><hr></div><h1>19. Conflict Resolution</h1><p>Suppose:</p><pre><code><code>Memory A:
User prefers Java
confidence = 0.80
timestamp = Jan

Memory B:
User prefers Go
confidence = 0.95
timestamp = Sep</code></code></pre><p>Resolution:</p><pre><code><code>                    Conflict
                       |
        +--------------+--------------+
        |              |              |
     Recency        Confidence      Explicitness
        |              |              |
        +--------------+--------------+
                       |
                       v
                  Resolver
                       |
                       v
             Current Memory = Go</code></code></pre><p>Important rule:</p><p><strong>Explicit user statements should have higher priority than inferred memories.</strong></p><p>Example:</p><pre><code><code>"I no longer use Java. I use Go now."
</code></code></pre><p>should strongly supersede an older inferred preference.</p><p>We can maintain:</p><pre><code><code>{
  "status": "superseded",
  "superseded_by": "mem456"
}</code></code></pre><p>instead of deleting the old memory.</p><div><hr></div><h1>20. Eviction Policies</h1><p>Different memory types need different policies.</p><h3>Short-term</h3><p>Use TTL:</p><pre><code><code>Session memory -&gt; 24 hours / 7 days</code></code></pre><p>depending on product requirements.</p><div><hr></div><h3>Episodic</h3><p>Use importance + recency:</p><pre><code><code>Low importance + old + never accessed
                    &#8595;
                  Evict</code></code></pre><div><hr></div><h3>Semantic</h3><p>Semantic memories should be much harder to evict.</p><p>Evict when:</p><pre><code><code>low confidence
contradicted
obsolete
never useful
user explicitly deletes it</code></code></pre><div><hr></div><h1>21. Memory Lifecycle</h1><p>The complete lifecycle becomes:</p><pre><code><code>                Conversation
                     |
                     v
              Short-Term Memory
                     |
                     v
                   Kafka
                     |
                     v
              Memory Extraction
                     |
                     v
             Candidate Memories
                     |
          +----------+----------+
          |                     |
          v                     v
      Episodic              Semantic
          |                     |
          +----------+----------+
                     |
                     v
              Deduplication
                     |
                     v
             Conflict Resolution
                     |
                     v
                Persistence
                     |
                     v
                Embeddings
                     |
                     v
              Vector Retrieval
                     |
                     v
                 Ranking
                     |
                     v
               LLM Context</code></code></pre><div><hr></div><h1>22. Personalization Layer</h1><p>Before invoking the LLM:</p><pre><code><code>User Query
    |
    v
Memory Retrieval
    |
    +---- Preferences
    +---- Relevant facts
    +---- Recent episodes
    +---- Current session
    |
    v
Personalization Context
    |
    v
LLM</code></code></pre><p>For example:</p><pre><code><code>User asks:
"Design a system for X."

Retrieved memories:

- User prefers Go
- User is preparing for system design interviews
- User prefers FR/NFR/API/DB/microservices format</code></code></pre><p>The LLM can then produce the response using those preferences without the user repeating them.</p><div><hr></div><h1>23. Important Design Principle</h1><p>Don&#8217;t put all memory into the LLM prompt.</p><p>Instead:</p><pre><code><code>                 Memory Store
                      |
                 Retrieval
                      |
                 Relevance
                      |
                 Compression
                      |
                   Top-K
                      |
                      v
              Small Context
                      |
                      v
                     LLM</code></code></pre><p>This controls:</p><ul><li><p>token cost</p></li><li><p>latency</p></li><li><p>irrelevant context</p></li><li><p>privacy exposure</p></li><li><p>hallucination risk</p></li></ul><div><hr></div><h1>24. End-to-End Request Flow</h1><p>For a new user request:</p><pre><code><code>1. User sends request
          |
2. Gateway authenticates user
          |
3. Fetch short-term context from Redis
          |
4. Generate query embedding
          |
5. Search semantic + episodic memories
          |
6. Apply user/tenant filters
          |
7. Rank memories
          |
8. Compress selected memories
          |
9. Build LLM context
          |
10. Call LLM
          |
11. Return response
          |
12. Publish conversation event to Kafka
          |
13. Async extraction worker processes it
          |
14. New memories are created/updated</code></code></pre><p>The key architectural decision is that <strong>memory extraction doesn&#8217;t block the user response</strong>.</p><pre><code><code>                 User Request
                      |
                      v
                 Memory Read
                      |
                      v
                     LLM
                      |
                      v
                  Response
                      |
                      |
              asynchronous
                      |
                      v
                    Kafka
                      |
                      v
              Memory Processing</code></code></pre><p>That keeps the online path fast while extraction, summarization, consolidation, and embedding generation happen asynchronously.</p>]]></content:encoded></item><item><title><![CDATA[HLD: Design an Agent Memory System]]></title><description><![CDATA[Design a memory system for an AI agent that allows it to remember useful information about users across conversations.]]></description><link>https://programmingappliedai.substack.com/p/hld-design-an-agent-memory-system</link><guid isPermaLink="false">https://programmingappliedai.substack.com/p/hld-design-an-agent-memory-system</guid><dc:creator><![CDATA[Shashank Mishra]]></dc:creator><pubDate>Sat, 12 Sep 2026 04:21:56 GMT</pubDate><enclosure url="iframe.php?url=https%3A%2F%2Fsubstackcdn.com%2Fimage%2Ffetch%2F%24s_%21riGX%21%2Cw_256%2Cc_limit%2Cf_auto%2Cq_auto%3Agood%2Cfl_progressive%3Asteep%2Fhttps%253A%252F%252Fsubstack-post-media.s3.amazonaws.com%252Fpublic%252Fimages%252F58e132e8-cd28-4037-b0ef-feabb2b68221_144x144.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>If you&#8217;re looking for paid 1:1 mentorship with a strong focus on Low-Level Design (LLD)&#8212;especially Multithreading and Concurrency&#8212;along with High-Level Design (HLD), Data Structures &amp; Algorithms (DSA), System Design, LLM/Generative AI systems, and research paper discussions, feel free to reach out.</p><p>The mentorship is tailored for interview preparation, backend engineering, distributed systems, AI infrastructure, and building a strong systems-thinking foundation.</p><p>&#128233; Contact: <a href="iframe.php?url=mailto%3Aprogrammingappliedai%40gmail.com">programmingappliedai@gmail.com</a></p><p>Yes. Let&#8217;s start <strong>from scratch</strong> and structure it exactly like an <strong>AI Engineer / SDE-2 HLD interview answer</strong>.</p><h1></h1><p>The system should support:</p><ul><li><p>Short-term memory</p></li><li><p>Long-term memory</p></li><li><p>Episodic memory</p></li><li><p>Semantic memory</p></li><li><p>Memory extraction</p></li><li><p>Memory retrieval</p></li><li><p>Summarization</p></li><li><p>Conflict resolution</p></li><li><p>Memory eviction</p></li><li><p>Personalization</p></li></ul><p>Example:</p><pre><code><code>Conversation 1:

User: I prefer Go for backend development.
Agent: Got it.

Conversation 2, several days later:

User: Suggest a backend project for me.

Agent:
Since you prefer Go and are interested in backend systems,
you could build a distributed rate limiter.</code></code></pre><p>The agent needs to retrieve the relevant memory before generating the response.</p><div><hr></div><h1>2. Functional Requirements</h1><ol><li><p>Store the current conversation as <strong>short-term memory</strong>.</p></li><li><p>Extract important information from conversations and convert it into <strong>long-term memories</strong>.</p></li><li><p>Support different memory types:</p><ul><li><p>Semantic</p></li><li><p>Episodic</p></li><li><p>Short-term</p></li><li><p>Long-term</p></li></ul></li><li><p>Retrieve relevant memories based on the current user query.</p></li><li><p>Support semantic/embedding-based memory search.</p></li><li><p>Update an existing memory when the user provides newer information.</p></li><li><p>Detect and resolve conflicting memories.</p></li><li><p>Summarize and consolidate multiple related memories.</p></li><li><p>Automatically expire or evict low-value/stale memories.</p></li><li><p>Allow users to explicitly view, update, or delete their memories.</p></li></ol><div><hr></div><h1>3. Non-Functional Requirements</h1><ol><li><p><strong>Low latency</strong></p><ul><li><p>Memory retrieval should add less than ~100 ms to the normal request path.</p></li></ul></li><li><p><strong>High availability</strong></p><ul><li><p>Target 99.99% availability for memory retrieval.</p></li></ul></li><li><p><strong>Scalability</strong></p><ul><li><p>Support millions of users and billions of memories.</p></li></ul></li><li><p><strong>Durability</strong></p><ul><li><p>Long-term memories should survive node/service failures.</p></li></ul></li><li><p><strong>Consistency</strong></p><ul><li><p>Memory updates must be durable.</p></li><li><p>Vector indexes can be eventually consistent.</p></li></ul></li><li><p><strong>Security</strong></p><ul><li><p>Strict user and tenant isolation.</p></li><li><p>Encryption at rest and in transit.</p></li></ul></li><li><p><strong>Privacy</strong></p><ul><li><p>Memory must never leak between users/tenants.</p></li></ul></li><li><p><strong>Cost efficiency</strong></p><ul><li><p>Don&#8217;t store every conversation permanently.</p></li><li><p>Minimize embedding and LLM calls.</p></li></ul></li><li><p><strong>Fault tolerance</strong></p><ul><li><p>Failure of embedding/vector services shouldn&#8217;t bring down the main agent.</p></li></ul></li><li><p><strong>Observability</strong></p></li></ol><ul><li><p>Track retrieval latency, hit rate, memory quality, conflicts, failures, and storage usage.</p></li></ul><div><hr></div><h1>4. Capacity Estimation</h1><p>Let&#8217;s assume:</p><pre><code><code>10M users
100 long-term memories/user</code></code></pre><p>Therefore:</p><pre><code><code>10M &#215; 100
= 1 Billion memories</code></code></pre><p>Assume each memory contains approximately:</p><pre><code><code>1 KB metadata + text</code></code></pre><p>Raw storage:</p><pre><code><code>1B &#215; 1 KB
&#8776; 1 TB</code></code></pre><p>Now consider embeddings.</p><p>For a 1536-dimensional FP32 vector:</p><pre><code><code>1536 &#215; 4 bytes
= 6 KB/vector</code></code></pre><p>Therefore:</p><pre><code><code>1B &#215; 6 KB
&#8776; 6 TB</code></code></pre><p>This doesn&#8217;t include:</p><pre><code><code>Vector index
Replication
Metadata
Backups
Storage overhead</code></code></pre><p>So we are looking at <strong>multi-terabyte distributed storage</strong>.</p><div><hr></div><h1>5. High-Level Architecture</h1><pre><code><code>                         &#9484;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9488;
                         &#9474;    Client    &#9474;
                         &#9492;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9516;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9496;
                                &#9474;
                                &#9660;
                         &#9484;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9488;
                         &#9474;  AI Agent    &#9474;
                         &#9492;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9516;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9496;
                                &#9474;
                                &#9660;
                      &#9484;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9488;
                      &#9474;  Memory Manager  &#9474;
                      &#9492;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9516;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9496;
                               &#9474;
              &#9484;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9532;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9488;
              &#9474;                &#9474;                 &#9474;
              &#9660;                &#9660;                 &#9660;
           Redis          Vector Database    PostgreSQL
        Short-term        Semantic Search    Source of Truth
           Memory
              &#9474;                &#9474;                 &#9474;
              &#9492;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9532;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9496;
                               &#9474;
                               &#9660;
                       Context Builder
                               &#9474;
                               &#9660;
                              LLM
                               &#9474;
                               &#9660;
                            Response


              ASYNCHRONOUS MEMORY PIPELINE

                         Conversation
                              &#9474;
                              &#9660;
                       Kafka / Queue
                              &#9474;
               &#9484;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9532;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9488;
               &#9660;              &#9660;              &#9660;
          Extraction     Summarization   Embedding
            Worker          Worker         Worker
               &#9474;              &#9474;              &#9474;
               &#9492;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9532;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9496;
                              &#9660;
                       Memory Storage</code></code></pre><div><hr></div><h1>6. Components</h1><h2>6.1 Memory Manager</h2><p>This is the main component responsible for memory operations.</p><p>It decides:</p><pre><code><code>Should I retrieve memory?
Should I write memory?
Which memories should be retrieved?
Which memories should be updated?</code></code></pre><div><hr></div><h2>6.2 Short-Term Memory</h2><p>Stores the current conversation.</p><p>Example:</p><pre><code><code>User:
Design a Kafka system.

Agent:
Sure...

User:
Now explain partitioning.</code></code></pre><p>The agent needs the previous messages to understand what &#8220;partitioning&#8221; refers to.</p><p>Redis is a good choice:</p><pre><code><code>Redis
  &#9474;
  &#9500;&#9472;&#9472; conversation_id
  &#9500;&#9472;&#9472; recent messages
  &#9492;&#9472;&#9472; TTL</code></code></pre><p>Short-term memory can expire after:</p><pre><code><code>hours / days</code></code></pre><p>depending on the product.</p><div><hr></div><h1>7. Long-Term Memory</h1><p>Important information gets promoted from short-term memory to long-term memory.</p><p>Example:</p><pre><code><code>User:
I usually work with Go and DynamoDB.</code></code></pre><p>Memory extraction produces:</p><pre><code><code>{
  "type": "semantic",
  "content": "User works primarily with Go and DynamoDB",
  "importance": 0.9,
  "confidence": 0.95
}</code></code></pre><p>This memory survives beyond the current conversation.</p><div><hr></div><h1>8. Episodic vs Semantic Memory</h1><p>This distinction is important in an interview.</p><h3>Episodic</h3><p>Represents <strong>events that happened</strong>.</p><pre><code><code>User discussed Kafka exactly-once semantics
during conversation conv_123.</code></code></pre><h3>Semantic</h3><p>Represents <strong>general knowledge about the user</strong>.</p><pre><code><code>User is interested in distributed systems.</code></code></pre><p>So:</p><pre><code><code>Episodic = What happened?

Semantic = What do we know?</code></code></pre><div><hr></div><h1>9. Memory Write Flow</h1><pre><code><code>User Conversation
       &#9474;
       &#9660;
Short-Term Memory
       &#9474;
       &#9660;
Memory Extraction
       &#9474;
       &#9660;
&#9484;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9488;
&#9474; Is this worth       &#9474;
&#9474; remembering?        &#9474;
&#9492;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9516;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9496;
          &#9474;
     &#9484;&#9472;&#9472;&#9472;&#9472;&#9524;&#9472;&#9472;&#9472;&#9472;&#9488;
     &#9474;         &#9474;
    No        Yes
     &#9474;         &#9474;
 Discard       &#9660;
          Importance
          + Confidence
               &#9474;
               &#9660;
          PostgreSQL
               &#9474;
               &#9660;
             Kafka
               &#9474;
               &#9660;
       Embedding Worker
               &#9474;
               &#9660;
          Vector DB</code></code></pre><p>The important design decision is:</p><blockquote><p><strong>We should not store every message as long-term memory.</strong></p></blockquote><p>Otherwise the memory database becomes noisy and expensive.</p><div><hr></div><h1>10. Memory Extraction</h1><p>We can use an LLM or a specialized extraction model.</p><p>Input:</p><pre><code><code>Conversation:

User: I'm preparing for backend interviews.
User: I mainly use Go.
User: I don't have much experience with Kubernetes.</code></code></pre><p>Output:</p><pre><code><code>[
  {
    "type": "goal",
    "content": "User is preparing for backend interviews"
  },
  {
    "type": "preference",
    "content": "User primarily uses Go"
  },
  {
    "type": "knowledge_gap",
    "content": "User has limited Kubernetes experience"
  }
]</code></code></pre><p>Then assign:</p><pre><code><code>importance
confidence
TTL</code></code></pre><div><hr></div><h1>11. Memory Retrieval</h1><p>When a new query arrives:</p><pre><code><code>User Query
    &#9474;
    &#9660;
Query Embedding
    &#9474;
    &#9660;
Vector DB
    &#9474;
    &#9660;
Top 20 memories
    &#9474;
    &#9660;
Metadata Filtering
    &#9474;
    &#9660;
Reranking
    &#9474;
    &#9660;
Top 3-5 memories
    &#9474;
    &#9660;
Context Builder
    &#9474;
    &#9660;
LLM</code></code></pre><p>We shouldn&#8217;t send 100 memories to the LLM.</p><p>Only the most relevant memories should be included.</p><div><hr></div><h1>12. Retrieval Ranking</h1><p>Vector similarity alone isn&#8217;t sufficient.</p><p>Use:</p><pre><code><code>score =
    &#945; &#215; semantic_similarity
  + &#946; &#215; importance
  + &#947; &#215; recency
  + &#948; &#215; frequency
  + &#949; &#215; confidence</code></code></pre><p>For example:</p><pre><code><code>Memory A

similarity = 0.91
importance = 0.95
recency = 0.80


Memory B

similarity = 0.95
importance = 0.30
recency = 0.20</code></code></pre><p>Memory A may be more useful despite slightly lower semantic similarity.</p><div><hr></div><h1>13. Database Design</h1><h2>PostgreSQL</h2><p>Acts as the <strong>source of truth</strong>.</p><p>Stores:</p><pre><code><code>memory_id
user_id
tenant_id
type
content
importance
confidence
version
status
source
created_at
updated_at
last_accessed_at
expires_at</code></code></pre><p>Example:</p><pre><code><code>{
  "memory_id": "mem_123",
  "user_id": "user_456",
  "type": "semantic",
  "content": "User prefers Go",
  "importance": 0.9,
  "confidence": 0.95,
  "version": 3,
  "status": "active"
}</code></code></pre><div><hr></div><h1>14. Vector Database</h1><p>Stores:</p><pre><code><code>memory_id
embedding
tenant_id
user_id
metadata</code></code></pre><p>Used for:</p><pre><code><code>semantic similarity search</code></code></pre><p>Possible technologies:</p><pre><code><code>Qdrant
Milvus
Weaviate
Pinecone
OpenSearch</code></code></pre><p>The important architectural point:</p><pre><code><code>PostgreSQL = Source of Truth

Vector DB = Search Index</code></code></pre><p>If the vector database is lost, we can regenerate the vectors from PostgreSQL.</p><div><hr></div><h1>15. Redis</h1><p>Use Redis for:</p><pre><code><code>Current conversation
Session state
Recent memories
Frequently accessed memories
Retrieval cache</code></code></pre><p>Example:</p><pre><code><code>conversation:user_123
        &#8595;
recent 20 messages
        &#8595;
TTL = 24 hours</code></code></pre><div><hr></div><h1>16. Kafka</h1><p>Kafka is useful for asynchronous processing.</p><p>Events:</p><pre><code><code>MemoryCreated
MemoryUpdated
MemoryDeleted
ConversationCompleted
EmbeddingRequired
MemoryConsolidationRequired</code></code></pre><p>Example:</p><pre><code><code>PostgreSQL
     &#9474;
     &#9660;
 MemoryCreated
     &#9474;
     &#9660;
   Kafka
     &#9474;
     &#9660;
Embedding Worker
     &#9474;
     &#9660;
Vector DB</code></code></pre><p>This prevents embedding generation from blocking the user request.</p><div><hr></div><h1>17. Memory Update &amp; Conflict Resolution</h1><p>Suppose the system remembers:</p><pre><code><code>v1:
User prefers Java</code></code></pre><p>Later:</p><pre><code><code>User:
I've switched to Go.</code></code></pre><p>Create:</p><pre><code><code>v2:
User prefers Go</code></code></pre><p>Mark:</p><pre><code><code>v1 &#8594; superseded
v2 &#8594; active</code></code></pre><p>Instead of simply overwriting the old record, maintain versions.</p><div><hr></div><h1>18. Conflict Resolution</h1><p>There are different types of conflicts.</p><h3>Explicit correction</h3><pre><code><code>"I no longer use Java."</code></code></pre><p>Strong signal &#8594; update memory.</p><h3>Contextual difference</h3><pre><code><code>"I use Java at work."
"I use Go for personal projects."</code></code></pre><p>Not a conflict.</p><p>Store:</p><pre><code><code>Java &#8594; work
Go &#8594; personal</code></code></pre><h3>Uncertain information</h3><p>If confidence is low:</p><pre><code><code>confidence = 0.4</code></code></pre><p>don&#8217;t immediately overwrite a high-confidence memory.</p><div><hr></div><h1>19. Memory Consolidation</h1><p>Over time we might have:</p><pre><code><code>"I like Go."

"I mostly use Go."

"Go is my preferred language."

"I use Go for backend."</code></code></pre><p>These can be consolidated into:</p><pre><code><code>User prefers Go for backend development.</code></code></pre><p>Flow:</p><pre><code><code>Related Memories
       &#9474;
       &#9660;
Consolidation Worker
       &#9474;
       &#9660;
Canonical Memory
       &#9474;
       &#9660;
Old Memories &#8594; Archived</code></code></pre><p>This reduces storage and improves retrieval quality.</p><div><hr></div><h1>20. Memory Eviction</h1><p>Some memories should disappear.</p><p>For example:</p><pre><code><code>"I'm working on this temporary project this week."</code></code></pre><p>Could have:</p><pre><code><code>TTL = 7 days</code></code></pre><p>While:</p><pre><code><code>"I prefer Go."</code></code></pre><p>could have no TTL.</p><p>Eviction can consider:</p><pre><code><code>importance
recency
access frequency
confidence
TTL</code></code></pre><p>Low-value stale memories are removed first.</p><div><hr></div><h1>21. API Design</h1><h3>Create Memory</h3><pre><code><code>POST /v1/memories</code></code></pre><pre><code><code>{
  "user_id": "user_123",
  "type": "semantic",
  "content": "User prefers Go",
  "importance": 0.9,
  "confidence": 0.95
}</code></code></pre><p>Response:</p><pre><code><code>{
  "memory_id": "mem_123",
  "status": "created"
}</code></code></pre><h3>Search Memory</h3><pre><code><code>POST /v1/memories/search</code></code></pre><pre><code><code>{
  "user_id": "user_123",
  "query": "What language does the user prefer?",
  "top_k": 5
}</code></code></pre><p>Response:</p><pre><code><code>{
  "memories": [
    {
      "memory_id": "mem_123",
      "type": "semantic",
      "content": "User prefers Go",
      "score": 0.94
    }
  ]
}</code></code></pre><h3>Update Memory</h3><pre><code><code>PUT /v1/memories/{memory_id}</code></code></pre><h3>Delete Memory</h3><pre><code><code>DELETE /v1/memories/{memory_id}</code></code></pre><h3>List User Memories</h3><pre><code><code>GET /v1/users/{user_id}/memories</code></code></pre><div><hr></div><h1>22. Complete Read Path</h1><pre><code><code>                    User Query
                        &#9474;
                        &#9660;
                  &#9484;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9488;
                  &#9474; AI Agent   &#9474;
                  &#9492;&#9472;&#9472;&#9472;&#9472;&#9472;&#9516;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9496;
                        &#9474;
                        &#9660;
                 Memory Manager
                        &#9474;
                        &#9660;
                 Query Embedding
                        &#9474;
                        &#9660;
                   Vector DB
                        &#9474;
                   Top 20
                        &#9474;
                        &#9660;
                Metadata Filter
                        &#9474;
                        &#9660;
                   Reranker
                        &#9474;
                      Top 5
                        &#9474;
                        &#9660;
                Context Builder
                        &#9474;
                        &#9660;
                       LLM
                        &#9474;
                        &#9660;
                     Answer</code></code></pre><div><hr></div><h1>23. Complete Write Path</h1><pre><code><code>                  Conversation
                       &#9474;
                       &#9660;
                Short-Term Memory
                       &#9474;
                       &#9660;
                Memory Extraction
                       &#9474;
                       &#9660;
              Importance/Confidence
                       &#9474;
                       &#9660;
                  PostgreSQL
                       &#9474;
                       &#9660;
                     Kafka
                       &#9474;
                       &#9660;
               Embedding Worker
                       &#9474;
                       &#9660;
                  Vector DB</code></code></pre><div><hr></div><h1>24. Multi-Tenant Isolation</h1><p>Every memory should contain:</p><pre><code><code>tenant_id
user_id
application_id</code></code></pre><p>Vector search should always apply these filters.</p><p>For example:</p><pre><code><code>tenant_id = tenant_123
AND user_id = user_456</code></code></pre><p>This is critical because a semantic search system must never return another user&#8217;s memory.</p><div><hr></div><h1>25. Failure Handling</h1><h3>Vector DB is down</h3><pre><code><code>Vector DB
    &#8595;
Unavailable
    &#8595;
Fallback to PostgreSQL</code></code></pre><p>For important exact memories, PostgreSQL can still be queried.</p><div><hr></div><h3>Embedding Service is down</h3><p>Don&#8217;t fail the user request.</p><p>Instead:</p><pre><code><code>Memory Update
     &#8595;
Kafka
     &#8595;
Retry
     &#8595;
Embedding Worker
     &#8595;
Vector DB</code></code></pre><div><hr></div><h3>Kafka is temporarily unavailable</h3><p>Use a transactional/outbox pattern so memory events aren&#8217;t lost.</p><pre><code><code>PostgreSQL
    &#9474;
    &#9500;&#9472;&#9472; Memory
    &#9492;&#9472;&#9472; Outbox Event
             &#9474;
             &#9660;
           Kafka</code></code></pre><div><hr></div><h1>26. Observability</h1><p>Track:</p><pre><code><code>memory_retrieval_latency
memory_search_hit_rate
memory_write_rate
memory_extraction_rate
memory_conflict_rate
memory_eviction_rate
memory_consolidation_rate</code></code></pre><p>Also track AI-specific metrics:</p><pre><code><code>retrieval_precision
retrieval_recall
memory_context_tokens
memory_token_savings
memory-induced hallucination rate</code></code></pre><div><hr></div><h1>27. Final Architecture</h1><pre><code><code>                              CLIENT
                                &#9474;
                                &#9660;
                           &#9484;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9488;
                           &#9474; AI Agent&#9474;
                           &#9492;&#9472;&#9472;&#9472;&#9472;&#9516;&#9472;&#9472;&#9472;&#9472;&#9496;
                                &#9474;
                                &#9660;
                      &#9484;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9488;
                      &#9474; Memory Manager   &#9474;
                      &#9492;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9516;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9496;
                               &#9474;
             &#9484;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9532;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9488;
             &#9474;                 &#9474;                 &#9474;
             &#9660;                 &#9660;                 &#9660;
          Redis            PostgreSQL        Vector DB
      Short-term          Source of Truth   Semantic Search
             &#9474;                 &#9474;                 &#9474;
             &#9492;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9532;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9496;
                               &#9474;
                               &#9660;
                       Context Builder
                               &#9474;
                               &#9660;
                              LLM
                               &#9474;
                               &#9660;
                            Response


                  ASYNC MEMORY PIPELINE
                               &#9474;
                               &#9660;
                             Kafka
                               &#9474;
             &#9484;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9532;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9488;
             &#9660;                 &#9660;                 &#9660;
        Extraction        Consolidation      Embedding
          Worker             Worker            Worker
             &#9474;                 &#9474;                 &#9474;
             &#9492;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9532;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9496;
                               &#9474;
                               &#9660;
                          Vector DB</code></code></pre><h2></h2><p><strong>Core architecture to remember:</strong></p><pre><code><code>Redis       &#8594; Short-term memory
PostgreSQL  &#8594; Durable source of truth
Vector DB   &#8594; Semantic retrieval
Kafka       &#8594; Async memory pipeline
LLM         &#8594; Extraction / summarization / reasoning</code></code></pre>]]></content:encoded></item><item><title><![CDATA[HLD: Design an AI Gateway for multiple LLM providers (OpenAI, Anthropic, Gemini, open-source). Explain model routing, fallback strategy, rate limiting, cost-aware scheduling, retries, and h monitoring]]></title><description><![CDATA[Below is an interview-ready HLD for an AI Gateway supporting multiple LLM providers such as OpenAI, Anthropic, Gemini, and self-hosted/open-source models]]></description><link>https://programmingappliedai.substack.com/p/hld-design-an-ai-gateway-for-multiple</link><guid isPermaLink="false">https://programmingappliedai.substack.com/p/hld-design-an-ai-gateway-for-multiple</guid><dc:creator><![CDATA[Shashank Mishra]]></dc:creator><pubDate>Tue, 01 Sep 2026 16:27:28 GMT</pubDate><enclosure url="iframe.php?url=https%3A%2F%2Fsubstackcdn.com%2Fimage%2Ffetch%2F%24s_%21riGX%21%2Cw_256%2Cc_limit%2Cf_auto%2Cq_auto%3Agood%2Cfl_progressive%3Asteep%2Fhttps%253A%252F%252Fsubstack-post-media.s3.amazonaws.com%252Fpublic%252Fimages%252F58e132e8-cd28-4037-b0ef-feabb2b68221_144x144.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>If you&#8217;re looking for paid 1:1 mentorship with a strong focus on Low-Level Design (LLD)&#8212;especially Multithreading and Concurrency&#8212;along with High-Level Design (HLD), Data Structures &amp; Algorithms (DSA), System Design, LLM/Generative AI systems, and research paper discussions, feel free to reach out.</p><p>The mentorship is tailored for interview preparation, backend engineering, distributed systems, AI infrastructure, and building a strong systems-thinking foundation.</p><p><span>&#128233; Contact: </span><a href="iframe.php?url=mailto%3Aprogrammingappliedai%40gmail.com">programmingappliedai@gmail.com</a></p><h1>1. Functional Requirements</h1><ol><li><p><strong>Unified LLM API</strong></p><ul><li><p>Provide a common API interface for all LLM providers.</p></li><li><p>Client should not need to know whether the request goes to OpenAI, Anthropic, Gemini, or an open-source model.</p></li></ul></li><li><p><strong>Intelligent Model Routing</strong></p><ul><li><p>Route requests based on:</p><ul><li><p>Model capability</p></li><li><p>Latency</p></li><li><p>Cost</p></li><li><p>Provider availability</p></li><li><p>Context-window requirements</p></li><li><p>Tenant preferences</p></li></ul></li><li><p>Example: route simple queries to a cheaper model and complex queries to a stronger model.</p></li></ul></li><li><p><strong>Fallback</strong></p><ul><li><p>If the selected provider/model fails, automatically route to another eligible model/provider.</p></li><li><p>Example:</p></li></ul></li></ol><pre><code><code>OpenAI &#8594; Anthropic &#8594; Gemini &#8594; Self-hosted</code></code></pre><ol><li><p><strong>Rate Limiting &amp; Quotas</strong></p><ul><li><p>Support limits at:</p><ul><li><p>Tenant/user level</p></li><li><p>API-key level</p></li><li><p>Provider level</p></li><li><p>Model level</p></li></ul></li><li><p>Support both RPM and TPM limits.</p></li></ul></li><li><p><strong>Cost-Aware Scheduling</strong></p><ul><li><p>Track input/output tokens and model prices.</p></li><li><p>Prefer the cheapest model satisfying the request&#8217;s latency and quality requirements.</p></li><li><p>Enforce tenant-level budgets.</p></li></ul></li><li><p><strong>Retries</strong></p><ul><li><p>Retry transient failures such as:</p><ul><li><p>HTTP 429</p></li><li><p>500/502/503</p></li><li><p>Connection timeout</p></li></ul></li><li><p>Use exponential backoff with jitter.</p></li><li><p>Avoid retrying permanent errors such as invalid API keys or malformed requests.</p></li></ul></li><li><p><strong>Health Monitoring</strong></p><ul><li><p>Continuously monitor:</p><ul><li><p>Error rate</p></li><li><p>Latency</p></li><li><p>Token throughput</p></li><li><p>Rate-limit responses</p></li><li><p>Provider availability</p></li></ul></li><li><p>Temporarily remove unhealthy models/providers from routing.</p></li></ul></li></ol><div><hr></div><h1>2. Non-Functional Requirements</h1><ol><li><p><strong>High Availability</strong></p><ul><li><p>Gateway should have no single point of failure.</p></li><li><p>Target availability: <strong>99.99%+</strong>.</p></li></ul></li><li><p><strong>Low Latency</strong></p><ul><li><p>Gateway overhead should ideally be <strong>&lt;10&#8211;20 ms</strong> excluding LLM latency.</p></li><li><p>Support streaming responses.</p></li></ul></li><li><p><strong>Scalability</strong></p><ul><li><p>Horizontally scale gateway instances.</p></li><li><p>Support millions of requests/day and thousands of concurrent streaming requests.</p></li></ul></li><li><p><strong>Fault Tolerance</strong></p><ul><li><p>Provider failures should not bring down the gateway.</p></li><li><p>Support retries, circuit breakers, fallback and graceful degradation.</p></li></ul></li><li><p><strong>Security</strong></p><ul><li><p>Encrypt provider API keys.</p></li><li><p>Authentication and authorization for clients.</p></li><li><p>Tenant isolation.</p></li><li><p>Don&#8217;t expose provider credentials to clients.</p></li></ul></li><li><p><strong>Observability</strong></p><ul><li><p>Distributed tracing.</p></li><li><p>Metrics and structured logs.</p></li><li><p>Track latency, cost, tokens, errors and fallback frequency.</p></li></ul></li><li><p><strong>Cost Efficiency</strong></p><ul><li><p>Avoid unnecessary calls to expensive models.</p></li><li><p>Support configurable cost budgets and routing policies.</p></li></ul></li></ol><div><hr></div><h1>3. High-Level Architecture</h1><pre><code><code>                         &#9484;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9488;
                         &#9474;     Clients      &#9474;
                         &#9474; Apps / Services   &#9474;
                         &#9492;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9516;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9496;
                                  &#9474;
                                  &#9660;
                         &#9484;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9488;
                         &#9474;   API Gateway    &#9474;
                         &#9474; Auth + Validation&#9474;
                         &#9492;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9516;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9496;
                                  &#9474;
                                  &#9660;
                    &#9484;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9488;
                    &#9474;       AI Gateway         &#9474;
                    &#9474;                          &#9474;
                    &#9474; Request Manager           &#9474;
                    &#9474; Model Router              &#9474;
                    &#9474; Rate Limiter              &#9474;
                    &#9474; Cost Manager              &#9474;
                    &#9474; Retry / Circuit Breaker   &#9474;
                    &#9492;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9516;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9496;
                                 &#9474;
                    &#9484;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9524;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9488;
                    &#9474;                         &#9474;
                    &#9660;                         &#9660;
             &#9484;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9488;          &#9484;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9488;
             &#9474; Model Router &#9474;          &#9474; Health Engine&#9474;
             &#9492;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9516;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9496;          &#9492;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9496;
                    &#9474;
       &#9484;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9532;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9516;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9488;
       &#9660;            &#9660;             &#9660;             &#9660;
 &#9484;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9488; &#9484;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9488; &#9484;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9488; &#9484;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9488;
 &#9474; OpenAI   &#9474; &#9474; Anthropic &#9474; &#9474; Gemini   &#9474; &#9474; Open-source &#9474;
 &#9474; Adapter  &#9474; &#9474; Adapter   &#9474; &#9474; Adapter  &#9474; &#9474; Adapter     &#9474;
 &#9492;&#9472;&#9472;&#9472;&#9472;&#9516;&#9472;&#9472;&#9472;&#9472;&#9472;&#9496; &#9492;&#9472;&#9472;&#9472;&#9472;&#9472;&#9516;&#9472;&#9472;&#9472;&#9472;&#9472;&#9496; &#9492;&#9472;&#9472;&#9472;&#9472;&#9516;&#9472;&#9472;&#9472;&#9472;&#9472;&#9496; &#9492;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9516;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9496;
      &#9474;              &#9474;            &#9474;               &#9474;
      &#9660;              &#9660;            &#9660;               &#9660;
   OpenAI        Anthropic      Gemini       vLLM/TGI</code></code></pre><div><hr></div><h1>4. Microservices Architecture</h1><h3>1. API Gateway</h3><p>Responsibilities:</p><ul><li><p>Authentication</p></li><li><p>API-key validation</p></li><li><p>Request validation</p></li><li><p>Tenant identification</p></li><li><p>Request size limits</p></li><li><p>TLS termination</p></li></ul><pre><code><code>Client
  &#8595;
API Gateway
  &#8595;
AI Gateway</code></code></pre><div><hr></div><h3>2. Request/Inference Service</h3><p>Responsible for:</p><ul><li><p>Normalizing requests</p></li><li><p>Creating request IDs</p></li><li><p>Managing streaming/non-streaming requests</p></li><li><p>Sending request to Model Router</p></li><li><p>Returning normalized response</p></li></ul><div><hr></div><h3>3. Model Router</h3><p>Core component.</p><p>It maintains a list of candidate models:</p><pre><code><code>Request
   &#8595;
Model Router
   &#8595;
Candidate Models

GPT-X
Claude-X
Gemini-X
Llama-X</code></code></pre><p>Routing score can be:</p><pre><code><code>Score =
    capability_score
  - latency_penalty
  - cost_penalty
  - failure_penalty</code></code></pre><p>Example:</p><pre><code><code>GPT      cost = $$
Claude   cost = $
Gemini   cost = $
Llama    cost = very low</code></code></pre><p>For a simple classification request:</p><pre><code><code>Llama &#8594; selected</code></code></pre><p>For complex reasoning:</p><pre><code><code>Claude/GPT &#8594; selected</code></code></pre><div><hr></div><h3>4. Provider Adapter Service</h3><p>Each provider has a standardized adapter.</p><pre><code><code>                 AI Gateway
                     |
        &#9484;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9532;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9488;
        &#9660;            &#9660;            &#9660;
    OpenAI        Anthropic     Gemini
    Adapter       Adapter       Adapter</code></code></pre><p>Adapters convert the internal format into provider-specific APIs.</p><p>Internal:</p><pre><code><code>{
  "model": "best",
  "messages": [],
  "temperature": 0.2
}</code></code></pre><p>OpenAI adapter converts it into OpenAI&#8217;s format.</p><p>Anthropic adapter converts it into Anthropic&#8217;s format.</p><p>This prevents provider-specific logic from leaking into the core gateway.</p><div><hr></div><h1>5. Rate Limiter</h1><p>Use <strong>Redis</strong> for distributed rate limiting.</p><p>Example:</p><pre><code><code>Tenant A
   &#9474;
   &#9500;&#9472;&#9472; 100 RPM
   &#9500;&#9472;&#9472; 1M TPM
   &#9492;&#9472;&#9472; $100/day

Tenant B
   &#9474;
   &#9500;&#9472;&#9472; 1000 RPM
   &#9500;&#9472;&#9472; 10M TPM
   &#9492;&#9472;&#9472; $1000/day</code></code></pre><p>Use <strong>Token Bucket</strong> or <strong>Leaky Bucket</strong>.</p><p>For LLMs, we need both:</p><pre><code><code>RPM = Requests Per Minute
TPM = Tokens Per Minute</code></code></pre><p>Example:</p><pre><code><code>Request contains 10,000 tokens

Check:
RPM quota
+
TPM quota

If either exceeded &#8594; 429</code></code></pre><div><hr></div><h1>6. Cost-Aware Scheduling</h1><p>Maintain model pricing:</p><pre><code><code>Model       Input       Output
--------------------------------
Model A     $5/M        $15/M
Model B     $1/M        $5/M
Model C     $0.2/M      $0.8/M</code></code></pre><p>For every request:</p><pre><code><code>estimated_cost =
input_tokens &#215; input_price
+
estimated_output_tokens &#215; output_price</code></code></pre><p>Router can use:</p><pre><code><code>Quality requirement
        +
Latency requirement
        +
Cost budget
        &#8595;
Candidate models
        &#8595;
Select cheapest suitable model</code></code></pre><p>Example:</p><pre><code><code>User asks:
"Translate this sentence"

Possible models:

GPT      $0.01
Claude   $0.008
Gemini   $0.004
Llama    $0.001

&#8594; Llama selected</code></code></pre><p>For complex reasoning:</p><pre><code><code>Quality requirement = HIGH

Llama &#10060;
Gemini &#9888;&#65039;
Claude &#9989;

&#8594; Claude selected</code></code></pre><div><hr></div><h1>7. Fallback Strategy</h1><p>Use <strong>priority-based fallback</strong>.</p><pre><code><code>Primary
   &#8595;
OpenAI GPT
   &#8595; failure
Anthropic Claude
   &#8595; failure
Gemini
   &#8595; failure
Self-hosted Llama</code></code></pre><p>But don&#8217;t fallback for every error.</p><h3>Retryable</h3><pre><code><code>429
500
502
503
Timeout
Connection reset</code></code></pre><h3>Non-retryable</h3><pre><code><code>400
Invalid request
Invalid API key
Context too large
Unsupported model</code></code></pre><div><hr></div><h1>8. Circuit Breaker</h1><p>Suppose OpenAI starts returning:</p><pre><code><code>70% requests &#8594; 503</code></code></pre><p>Health service marks it unhealthy.</p><pre><code><code>             OpenAI
               &#9474;
          Circuit OPEN
               &#9474;
               X
               
Requests &#8594; Anthropic</code></code></pre><p>After a cooldown:</p><pre><code><code>OPEN
 &#8595;
HALF-OPEN
 &#8595;
Send few requests
 &#8595;
Healthy &#8594; CLOSED</code></code></pre><p>This prevents sending thousands of failing requests to a broken provider.</p><div><hr></div><h1>9. Retry Strategy</h1><p>Use exponential backoff + jitter.</p><pre><code><code>Attempt 1 &#8594; immediate
Attempt 2 &#8594; 100ms
Attempt 3 &#8594; 300ms
Attempt 4 &#8594; 700ms</code></code></pre><p>With jitter:</p><pre><code><code>delay = base &#215; 2^attempt + random()</code></code></pre><p>Also enforce:</p><pre><code><code>max_retries = 2 or 3</code></code></pre><p>Important: <strong>don&#8217;t retry blindly</strong>, especially for streaming requests or requests that may have already been processed.</p><p>Use an idempotency key where supported.</p><div><hr></div><h1>10. Health Monitoring</h1><p>Create a <strong>Health Service</strong>.</p><p>Monitor every provider/model:</p><pre><code><code>Provider
 &#9500;&#9472;&#9472; Availability
 &#9500;&#9472;&#9472; P50 latency
 &#9500;&#9472;&#9472; P95 latency
 &#9500;&#9472;&#9472; P99 latency
 &#9500;&#9472;&#9472; Error rate
 &#9500;&#9472;&#9472; 429 rate
 &#9500;&#9472;&#9472; Token throughput
 &#9492;&#9472;&#9472; Cost</code></code></pre><p>Example:</p><pre><code><code>OpenAI GPT
Error Rate:    2%
P95:           1.2 sec
429 Rate:      0.5%
Status:        HEALTHY

Claude
Error Rate:    35%
P95:           5 sec
Status:        UNHEALTHY</code></code></pre><p>Router then automatically reduces or stops traffic to Claude.</p><div><hr></div><h1>11. API Design</h1><h3>Generate Completion</h3><pre><code><code>POST /v1/chat/completions</code></code></pre><p>Request:</p><pre><code><code>{
  "model": "auto",
  "messages": [
    {
      "role": "user",
      "content": "Explain distributed systems"
    }
  ],
  "temperature": 0.2,
  "max_tokens": 1000,
  "stream": true
}</code></code></pre><p>Response:</p><pre><code><code>{
  "request_id": "req_123",
  "model": "claude-x",
  "provider": "anthropic",
  "usage": {
    "input_tokens": 100,
    "output_tokens": 500
  },
  "cost": 0.004
}</code></code></pre><p>For streaming:</p><pre><code><code>Client
  &#8595;
AI Gateway
  &#8595;
Provider

token &#8594; token &#8594; token &#8594; token
  &#8593;
stream back to client</code></code></pre><div><hr></div><h3>Model Information</h3><pre><code><code>GET /v1/models</code></code></pre><p>Response:</p><pre><code><code>{
  "models": [
    {
      "id": "model-a",
      "provider": "openai",
      "context_window": 128000,
      "input_cost": 5,
      "output_cost": 15,
      "healthy": true
    }
  ]
}</code></code></pre><div><hr></div><h3>Usage</h3><pre><code><code>GET /v1/usage</code></code></pre><p>Response:</p><pre><code><code>{
  "tenant_id": "tenant_123",
  "requests": 120000,
  "input_tokens": 50000000,
  "output_tokens": 10000000,
  "cost": 245.50
}</code></code></pre><div><hr></div><h3>Routing Configuration</h3><pre><code><code>PUT /v1/routing/policy</code></code></pre><p>Request:</p><pre><code><code>{
  "strategy": "cost_optimized",
  "fallback": [
    "anthropic",
    "gemini",
    "self-hosted"
  ],
  "max_cost_per_request": 0.05
}</code></code></pre><div><hr></div><h1>12. Database Choice</h1><p>Use different databases for different workloads.</p><div class="highlighted_code_block" data-attrs="{&quot;language&quot;:&quot;plaintext&quot;,&quot;nodeId&quot;:&quot;4b941b01-a662-4a89-ae30-80170d8f640c&quot;}" data-component-name="HighlightedCodeBlockToDOM"><pre class="shiki"><code class="language-plaintext">| Data                    | Database                 | Reason                          |
| ----------------------- | ------------------------ | ------------------------------- |
| Tenant/configuration    | PostgreSQL               | Strong consistency + relational |
| Model/provider metadata | PostgreSQL               | Configuration data              |
| Rate limiting           | Redis                    | Very low latency                |
| Cost/usage events       | Kafka + ClickHouse       | High-volume analytics           |
| Health metrics          | Prometheus               | Time-series metrics             |
| Logs                    | Elasticsearch/OpenSearch | Log search                      |
| Secrets                 | Vault/KMS                | Secure credential storage       |
</code></pre></div><div><hr></div><h1>13. Important DB Schemas</h1><h3>tenants</h3><pre><code><code>tenant_id PK
name
status
monthly_budget
created_at</code></code></pre><h3>models</h3><pre><code><code>model_id PK
provider
model_name
context_window
input_price
output_price
max_rpm
max_tpm
status</code></code></pre><h3>routing_policies</h3><pre><code><code>policy_id PK
tenant_id
strategy
primary_model
fallback_models
max_latency
max_cost</code></code></pre><h3>usage</h3><pre><code><code>request_id PK
tenant_id
model_id
provider
input_tokens
output_tokens
latency
cost
status
created_at</code></code></pre><div><hr></div><h1>14. Kafka Usage</h1><p>Kafka can be used for asynchronous events:</p><pre><code><code>LLM Request
     &#9474;
     &#9660;
AI Gateway
     &#9474;
     &#9500;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#8594; Provider
     &#9474;
     &#9492;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#8594; Kafka
                         &#9474;
             &#9484;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9532;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9488;
             &#9660;           &#9660;           &#9660;
         Cost Service  Analytics  Monitoring</code></code></pre><p>Events:</p><pre><code><code>LLM_REQUEST_COMPLETED
LLM_REQUEST_FAILED
MODEL_FALLBACK
PROVIDER_RATE_LIMITED
MODEL_HEALTH_CHANGED</code></code></pre><p>This keeps the request path fast.</p><div><hr></div><h1>15. Redis Usage</h1><p>Redis is used for:</p><pre><code><code>1. Rate limiting
2. Provider health state
3. Circuit breaker state
4. Model routing cache
5. Tenant quotas
6. Short-lived request metadata</code></code></pre><p>Example:</p><pre><code><code>rate_limit:{tenant_id}
quota:{tenant_id}
health:{provider}:{model}
circuit:{provider}</code></code></pre><div><hr></div><h1>16. Complete Request Flow</h1><pre><code><code>Client
  &#9474;
  &#9660;
API Gateway
  &#9474;
  &#9500;&#9472;&#9472; Authentication
  &#9500;&#9472;&#9472; Authorization
  &#9492;&#9472;&#9472; Request validation
  &#9474;
  &#9660;
Rate Limiter
  &#9474;
  &#9500;&#9472;&#9472; RPM check
  &#9492;&#9472;&#9472; TPM check
  &#9474;
  &#9660;
Request Service
  &#9474;
  &#9660;
Model Router
  &#9474;
  &#9500;&#9472;&#9472; Cost
  &#9500;&#9472;&#9472; Quality
  &#9500;&#9472;&#9472; Latency
  &#9500;&#9472;&#9472; Health
  &#9492;&#9472;&#9472; Tenant policy
  &#9474;
  &#9660;
Provider Adapter
  &#9474;
  &#9660;
OpenAI / Anthropic / Gemini / vLLM
  &#9474;
  &#9660;
Response
  &#9474;
  &#9500;&#9472;&#9472; Token usage
  &#9500;&#9472;&#9472; Cost calculation
  &#9500;&#9472;&#9472; Latency
  &#9492;&#9472;&#9472; Provider status
  &#9474;
  &#9500;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#8594; Kafka &#8594; Analytics
  &#9474;
  &#9492;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#8594; Client</code></code></pre><div><hr></div><h1>17. Key Interview Design Decisions</h1><p><strong>Why adapters?</strong></p><p>To isolate provider-specific APIs and allow adding a new provider without modifying routing logic.</p><p><strong>Why Redis for rate limiting?</strong></p><p>Rate limiting is on the hot path and requires low-latency atomic operations across multiple gateway instances.</p><p><strong>Why Kafka for usage?</strong></p><p>Usage events can be extremely high volume. Kafka decouples request processing from analytics, billing and monitoring.</p><p><strong>Why PostgreSQL?</strong></p><p>Tenant, model and routing configurations require transactions and strong consistency.</p><p><strong>Why Prometheus?</strong></p><p>Health and latency metrics are naturally time-series data and need efficient aggregation.</p><p><strong>How do we avoid one provider outage affecting the entire system?</strong></p><pre><code><code>Health checks
+
Circuit breaker
+
Retries
+
Fallback
+
Multi-provider routing</code></code></pre><p><strong>How do we minimize cost?</strong></p><pre><code><code>Cost-aware router
+
Model capability classification
+
Tenant budgets
+
Token estimation
+
Usage tracking</code></code></pre><p>The core idea is to make the gateway <strong>provider-agnostic</strong>: clients talk to one API, while the gateway dynamically decides <strong>which model, which provider, and whether to retry/fallback</strong>, based on <strong>cost + quality + latency + health + tenant policy</strong>.</p>]]></content:encoded></item><item><title><![CDATA[HLD: Design a Vector Database Infrastructure storing 10 billion embeddings with real-time updates. ]]></title><description><![CDATA[Explain sharding, indexing (HNSW/IVF-PQ), replication, filtering, metadata storage, and disaster recovery.]]></description><link>https://programmingappliedai.substack.com/p/hld-design-a-vector-database-infrastructure</link><guid isPermaLink="false">https://programmingappliedai.substack.com/p/hld-design-a-vector-database-infrastructure</guid><dc:creator><![CDATA[Shashank Mishra]]></dc:creator><pubDate>Tue, 18 Aug 2026 16:56:10 GMT</pubDate><enclosure url="iframe.php?url=https%3A%2F%2Fsubstackcdn.com%2Fimage%2Ffetch%2F%24s_%21riGX%21%2Cw_256%2Cc_limit%2Cf_auto%2Cq_auto%3Agood%2Cfl_progressive%3Asteep%2Fhttps%253A%252F%252Fsubstack-post-media.s3.amazonaws.com%252Fpublic%252Fimages%252F58e132e8-cd28-4037-b0ef-feabb2b68221_144x144.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>If you&#8217;re looking for paid 1:1 mentorship with a strong focus on Low-Level Design (LLD)&#8212;especially Multithreading and Concurrency&#8212;along with High-Level Design (HLD), Data Structures &amp; Algorithms (DSA), System Design, LLM/Generative AI systems, and research paper discussions, feel free to reach out.</p><p>The mentorship is tailored for interview preparation, backend engineering, distributed systems, AI infrastructure, and building a strong systems-thinking foundation.</p><p><span>&#128233; Contact: </span><a href="iframe.php?url=mailto%3Aprogrammingappliedai%40gmail.com">programmingappliedai@gmail.com</a></p><h2></h2><h3>1. Requirements</h3><p><strong>Functional</strong></p><ul><li><p>Store and search <strong>10B+ embeddings</strong> with configurable dimensions such as 768/1536.</p></li><li><p>Support <strong>real-time insert, update and delete</strong> of vectors.</p></li><li><p>Support approximate nearest-neighbor search using <strong>HNSW / IVF-PQ</strong>.</p></li><li><p>Support metadata filtering such as <code>tenant_id</code>, <code>category</code>, <code>timestamp</code>, etc.</p></li><li><p>Support top-K similarity search with optional filters.</p></li><li><p>Provide replication, backup and disaster recovery.</p></li></ul><p><strong>Non-functional</strong></p><ul><li><p>Search latency: <strong>&lt;100 ms p95</strong> for normal workloads.</p></li><li><p>High availability: <strong>99.99%+</strong>.</p></li><li><p>Horizontally scalable by adding nodes.</p></li><li><p>No data loss for acknowledged writes; target <strong>RPO &#8776; 0</strong> with synchronous/replicated WAL depending on deployment.</p></li><li><p>Support tenant isolation and predictable performance under noisy-neighbor workloads.</p></li></ul><div><hr></div><h1>2. High-Level Architecture</h1><pre><code><code>                        &#9484;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9488;
                        &#9474;   Client / Apps  &#9474;
                        &#9492;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9516;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9496;
                                 &#9474;
                                 &#9660;
                       &#9484;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9488;
                       &#9474;   API Gateway     &#9474;
                       &#9474; Auth / Rate Limit &#9474;
                       &#9492;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9516;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9496;
                                 &#9474;
                 &#9484;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9524;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9488;
                 &#9660;                                &#9660;
        &#9484;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9488;              &#9484;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9488;
        &#9474; Query Coordinator&#9474;              &#9474;  Write Service  &#9474;
        &#9492;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9516;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9496;              &#9492;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9516;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9496;
                 &#9474;                                &#9474;
                 &#9660;                                &#9660;
        &#9484;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9488;              &#9484;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9488;
        &#9474; Query Planner   &#9474;              &#9474; WAL / Log       &#9474;
        &#9474; + Filter Engine &#9474;              &#9474; Kafka           &#9474;
        &#9492;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9516;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9496;              &#9492;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9516;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9496;
                 &#9474;                                &#9474;
                 &#9660;                                &#9660;
        &#9484;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9488;
        &#9474;              Shard Router / Metadata             &#9474;
        &#9492;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9516;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9496;
                        &#9474;
             &#9484;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9532;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9488;
             &#9660;          &#9660;          &#9660;
          Shard 1    Shard 2     Shard N
          &#9484;&#9472;&#9472;&#9472;&#9472;&#9472;&#9488;    &#9484;&#9472;&#9472;&#9472;&#9472;&#9472;&#9488;     &#9484;&#9472;&#9472;&#9472;&#9472;&#9472;&#9488;
          &#9474;Index&#9474;    &#9474;Index&#9474;     &#9474;Index&#9474;
          &#9474;HNSW &#9474;    &#9474;IVF-PQ&#9474;    &#9474;HNSW &#9474;
          &#9500;&#9472;&#9472;&#9472;&#9472;&#9472;&#9508;    &#9500;&#9472;&#9472;&#9472;&#9472;&#9472;&#9508;     &#9500;&#9472;&#9472;&#9472;&#9472;&#9472;&#9508;
          &#9474;Vector&#9474;   &#9474;Vector&#9474;    &#9474;Vector&#9474;
          &#9474;Store &#9474;   &#9474;Store &#9474;    &#9474;Store &#9474;
          &#9500;&#9472;&#9472;&#9472;&#9472;&#9472;&#9508;    &#9500;&#9472;&#9472;&#9472;&#9472;&#9472;&#9508;     &#9500;&#9472;&#9472;&#9472;&#9472;&#9472;&#9508;
          &#9474;Meta  &#9474;    &#9474;Meta  &#9474;    &#9474;Meta  &#9474;
          &#9492;&#9472;&#9472;&#9472;&#9472;&#9472;&#9496;    &#9492;&#9472;&#9472;&#9472;&#9472;&#9472;&#9496;     &#9492;&#9472;&#9472;&#9472;&#9472;&#9472;&#9496;
             &#9474;          &#9474;           &#9474;
             &#9492;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9532;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9496;
                        &#9660;
                Object Storage
               Backups / Snapshots</code></code></pre><div><hr></div><h1>3. Data Model</h1><p>A vector record can look like:</p><pre><code><code>Vector {
    vector_id
    tenant_id
    embedding
    dimension
    metadata
    created_at
    updated_at
    version
    deleted
}</code></code></pre><p>Example metadata:</p><pre><code><code>{
  "tenant_id": "tenant_123",
  "category": "electronics",
  "language": "en",
  "timestamp": 1755000000
}</code></code></pre><p>Separate vector and metadata storage is useful because metadata filtering and vector similarity have very different access patterns.</p><div><hr></div><h1>4. Sharding</h1><p>At <strong>10B vectors</strong>, a single machine is impossible.</p><p>Assume:</p><pre><code><code>10B vectors
1536 dimensions
FP32 = 4 bytes</code></code></pre><p>Raw vector storage:</p><pre><code><code>10B &#215; 1536 &#215; 4
&#8776; 61.4 TB</code></code></pre><p>And this excludes:</p><ul><li><p>HNSW index</p></li><li><p>metadata</p></li><li><p>replication</p></li><li><p>WAL</p></li><li><p>operating-system overhead</p></li><li><p>temporary indexing memory</p></li></ul><p>With 3&#215; replication, raw vector data alone becomes roughly:</p><pre><code><code>61.4 TB &#215; 3 &#8776; 184 TB</code></code></pre><p>Therefore we horizontally shard the dataset.</p><h3>Sharding strategy</h3><p>Use <strong>consistent hashing / hash-based partitioning</strong>:</p><pre><code><code>hash(tenant_id + vector_id) &#8594; shard</code></code></pre><p>For very large tenants, use:</p><pre><code><code>hash(vector_id) &#8594; shard</code></code></pre><p>rather than putting an entire tenant on one shard.</p><p>A logical partition could be:</p><pre><code><code>Partition P1 &#8594; Shard 17
Partition P2 &#8594; Shard 42
Partition P3 &#8594; Shard 83
...</code></code></pre><p>Use <strong>virtual shards</strong> so that physical nodes can be added or removed without massive data movement.</p><div><hr></div><h1>5. Query Flow</h1><p>For:</p><pre><code><code>Top K similar vectors
where category = "phone"</code></code></pre><p>the flow is:</p><pre><code><code>Client
  &#8595;
API Gateway
  &#8595;
Query Coordinator
  &#8595;
Metadata / Filter Planner
  &#8595;
Determine relevant shards
  &#8595;
Parallel ANN search
  &#8595;
Shard 1 &#8594; top K
Shard 2 &#8594; top K
Shard 3 &#8594; top K
...
  &#8595;
Merge candidates
  &#8595;
Optional exact distance calculation
  &#8595;
Global Top K
  &#8595;
Client</code></code></pre><p>If searching 100 shards and requesting <code>K=10</code>, each shard may return:</p><pre><code><code>local_top_k = 50</code></code></pre><p>Then the coordinator merges:</p><pre><code><code>100 &#215; 50 = 5000 candidates</code></code></pre><p>and performs exact distance computation on those candidates.</p><p>This gives better recall than directly returning each shard&#8217;s top 10.</p><div><hr></div><h1>6. Indexing &#8212; HNSW</h1><p><strong>HNSW</strong> creates a graph of vectors.</p><pre><code><code>        A -------- B
       /            \
      C ---- D ------ E
       \             /
        F -----------G</code></code></pre><p>Each vector is connected to nearby vectors.</p><p>Search starts from an entry point and traverses the graph toward increasingly similar vectors.</p><h3>Advantages</h3><ul><li><p>Excellent recall.</p></li><li><p>Very low query latency.</p></li><li><p>Good for relatively dynamic workloads.</p></li></ul><h3>Disadvantages</h3><ul><li><p>High memory consumption.</p></li><li><p>Expensive updates.</p></li><li><p>Large graph at 10B vectors.</p></li></ul><p>Therefore, we generally don&#8217;t maintain one gigantic HNSW graph.</p><p>Instead:</p><pre><code><code>Shard
 &#9500;&#9472;&#9472; Segment 1 &#8594; HNSW
 &#9500;&#9472;&#9472; Segment 2 &#8594; HNSW
 &#9500;&#9472;&#9472; Segment 3 &#8594; HNSW
 &#9492;&#9472;&#9472; ...</code></code></pre><div><hr></div><h1>7. Indexing &#8212; IVF-PQ</h1><p>For extremely large datasets, <strong>IVF-PQ</strong> is attractive because it substantially reduces memory/storage requirements.</p><h3>IVF</h3><p>First cluster vectors:</p><pre><code><code>             Vector Space

        C1        C2

              C3

    C4                 C5</code></code></pre><p>During search:</p><pre><code><code>Query
  &#8595;
Find nearest clusters
  &#8595;
Search only those clusters</code></code></pre><p>Instead of searching 10B vectors, we may search only vectors belonging to the closest few clusters.</p><h3>PQ</h3><p><strong>Product Quantization</strong> compresses vectors into compact codes.</p><p>For example:</p><pre><code><code>1536-dimensional vector
        &#8595;
Split into sub-vectors
        &#8595;
Quantize each sub-vector
        &#8595;
Compact code</code></code></pre><p>This significantly reduces memory requirements.</p><h3>HNSW vs IVF-PQ</h3><div class="highlighted_code_block" data-attrs="{&quot;language&quot;:&quot;plaintext&quot;,&quot;nodeId&quot;:&quot;8e86e9ec-cb68-40fd-9da3-778e0216b3a3&quot;}" data-component-name="HighlightedCodeBlockToDOM"><pre class="shiki"><code class="language-plaintext">| Feature   | HNSW             | IVF-PQ           |
| --------- | ---------------- | ---------------- |
| Recall    | Very high        | High, tunable    |
| Latency   | Very low         | Low              |
| Memory    | High             | Much lower       |
| Updates   | Easier           | More complex     |
| 10B scale | Expensive        | More suitable    |
| Best use  | Hot/dynamic data | Massive datasets |
</code></pre></div><p>A practical architecture can use <strong>HNSW for recent/hot segments</strong> and <strong>IVF-PQ for large historical segments</strong>.</p><div><hr></div><h1>8. Real-Time Updates</h1><p>This is one of the hardest parts.</p><p>Building a huge ANN index after every write is impossible.</p><p>Use a <strong>mutable + immutable segment architecture</strong>.</p><pre><code><code>                    Incoming writes
                          &#9474;
                          &#9660;
                     WAL / Kafka
                          &#9474;
                          &#9660;
                  Mutable Memtable
                          &#9474;
                 &#9484;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9524;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9488;
                 &#9660;                 &#9660;
             HNSW index       Metadata index
                 &#9474;
                 &#9660;
           Periodic flush
                 &#9474;
                 &#9660;
          Immutable Segment
                 &#9474;
                 &#9660;
         Background compaction</code></code></pre><h3>Write path</h3><pre><code><code>Client
  &#8595;
Write API
  &#8595;
WAL
  &#8595;
Replicas
  &#8595;
Memtable
  &#8595;
Realtime HNSW</code></code></pre><p>Once a segment reaches a threshold:</p><pre><code><code>Memtable &#8594; Immutable segment</code></code></pre><p>Background workers then build/optimize IVF-PQ indexes.</p><p>This gives low write latency without continuously rebuilding the entire index.</p><div><hr></div><h1>9. Updates and Deletes</h1><p>Never physically modify a huge immutable segment immediately.</p><p>For an update:</p><pre><code><code>vector_id = 123
version = 7</code></code></pre><p>write:</p><pre><code><code>version = 8</code></code></pre><p>and mark version 7 obsolete.</p><p>For delete:</p><pre><code><code>tombstone(vector_id)</code></code></pre><p>During query:</p><pre><code><code>candidate
   &#8595;
metadata/version check
   &#8595;
if deleted/old &#8594; discard</code></code></pre><p>Later, compaction removes obsolete vectors and tombstones.</p><p>This is similar to an <strong>LSM-tree style architecture</strong>.</p><div><hr></div><h1>10. Metadata Storage</h1><p>Do not store large metadata blobs inside the ANN index.</p><p>Use a separate metadata store:</p><pre><code><code>Vector ID
   &#9474;
   &#9500;&#9472;&#9472; ANN index
   &#9474;
   &#9492;&#9472;&#9472; Metadata Store
          &#9500;&#9472;&#9472; tenant_id
          &#9500;&#9472;&#9472; category
          &#9500;&#9472;&#9472; timestamp
          &#9500;&#9472;&#9472; language
          &#9492;&#9472;&#9472; attributes</code></code></pre><p>Depending on requirements:</p><ul><li><p><strong>RocksDB</strong> &#8594; local metadata/index state.</p></li><li><p><strong>PostgreSQL</strong> &#8594; transactional metadata with moderate scale.</p></li><li><p><strong>Cassandra/ScyllaDB</strong> &#8594; massive distributed metadata.</p></li><li><p><strong>Object storage</strong> &#8594; immutable historical metadata/segments.</p></li></ul><p>For 10B-scale infrastructure, I would favor a distributed KV store for metadata that needs horizontal scaling.</p><div><hr></div><h1>11. Filtering</h1><p>Filtering is tricky because:</p><pre><code><code>similarity search
+
metadata filtering</code></code></pre><p>must be performed efficiently.</p><p>Example:</p><pre><code><code>Find 20 nearest vectors
WHERE
    tenant_id = 123
    AND category = "car"
    AND language = "en"</code></code></pre><h3>Approach 1 &#8212; Pre-filter</h3><p>First identify matching IDs:</p><pre><code><code>Metadata Index
      &#8595;
1M matching vectors
      &#8595;
ANN search</code></code></pre><p>Good when filters are highly selective.</p><h3>Approach 2 &#8212; Post-filter</h3><pre><code><code>ANN search
   &#8595;
1000 candidates
   &#8595;
metadata filter
   &#8595;
20 results</code></code></pre><p>Good when filter selectivity is low.</p><h3>Better approach</h3><p>Use an adaptive planner:</p><pre><code><code>Estimate filter selectivity
        &#8595;
Highly selective?
   /           \
 Yes            No
 &#8595;               &#8595;
Pre-filter     ANN first</code></code></pre><p>For frequently used fields, maintain bitmap/inverted indexes.</p><div><hr></div><h1>12. Replication</h1><p>Each shard has multiple replicas:</p><pre><code><code>Shard 17

Replica A &#8594; Node 1
Replica B &#8594; Node 8
Replica C &#8594; Node 21</code></code></pre><p>Use <strong>3 replicas</strong> across different failure domains.</p><pre><code><code>        Shard Leader
        /     |     \
       /      |      \
 Replica 1  Replica 2  Replica 3
 Zone A      Zone B      Zone C</code></code></pre><h3>Writes</h3><pre><code><code>Client
  &#8595;
Leader
  &#8595;
WAL
  &#8595;
Replicas
  &#8595;
Quorum ACK</code></code></pre><p>For stronger durability:</p><pre><code><code>W + R &gt; N</code></code></pre><p>For example:</p><pre><code><code>N = 3
W = 2
R = 2</code></code></pre><p>A leader failure triggers leader election.</p><div><hr></div><h1>13. Read Scaling</h1><p>ANN queries are generally read-heavy.</p><p>Therefore:</p><pre><code><code>               Query Coordinator
                 /    |    \
                /     |     \
             Replica Replica Replica</code></code></pre><p>Queries can be distributed across replicas.</p><p>Use:</p><ul><li><p>replica-aware routing</p></li><li><p>load-based routing</p></li><li><p>cache-aware routing</p></li><li><p>tenant-aware routing</p></li></ul><p>Avoid sending every query to the leader.</p><div><hr></div><h1>14. Hot/Cold Architecture</h1><p>10B embeddings may not have uniform access patterns.</p><p>Use:</p><pre><code><code>HOT
 &#8595;
RAM + HNSW
 &#8595;
Warm
 &#8595;
SSD + IVF
 &#8595;
COLD
 &#8595;
Object Storage + IVF-PQ</code></code></pre><p>For example:</p><pre><code><code>Recent 100M vectors &#8594; HNSW
Older 9.9B vectors &#8594; IVF-PQ</code></code></pre><p>Search both and merge results.</p><p>This significantly reduces RAM requirements.</p><div><hr></div><h1>15. Disaster Recovery</h1><p>Use multiple layers.</p><h3>WAL</h3><p>Every mutation goes into durable WAL:</p><pre><code><code>Write
 &#8595;
WAL
 &#8595;
Vector Store</code></code></pre><p>Kafka/object storage can retain the mutation stream.</p><h3>Snapshots</h3><p>Periodically create:</p><pre><code><code>Shard snapshot
+
ANN index
+
Metadata
+
WAL checkpoint</code></code></pre><p>Store snapshots in durable object storage.</p><p>Example:</p><pre><code><code>Object Storage

bucket/
 &#9500;&#9472;&#9472; shard-001/
 &#9474;    &#9500;&#9472;&#9472; snapshot-100
 &#9474;    &#9500;&#9472;&#9472; snapshot-200
 &#9474;    &#9492;&#9472;&#9472; WAL-offset
 &#9500;&#9472;&#9472; shard-002/
 &#9492;&#9472;&#9472; ...</code></code></pre><h3>Recovery</h3><pre><code><code>Latest snapshot
      &#8595;
Restore
      &#8595;
Replay WAL
      &#8595;
Rebuild missing indexes
      &#8595;
Replica synchronization
      &#8595;
Shard becomes healthy</code></code></pre><p>For regional disaster recovery:</p><pre><code><code>Region A
  &#8595; async replication
Region B</code></code></pre><p>For critical workloads, keep a warm standby cluster.</p><div><hr></div><h1>16. Failure Handling</h1><h3>Node failure</h3><pre><code><code>Node dies
   &#8595;
Shard coordinator detects failure
   &#8595;
Route traffic to replica
   &#8595;
Create replacement replica
   &#8595;
Stream missing data</code></code></pre><h3>Replica failure</h3><p>Rebuild from:</p><pre><code><code>healthy replica
+
WAL</code></code></pre><h3>Corrupted index</h3><p>Don&#8217;t treat the ANN index as the source of truth.</p><p>The source of truth should be:</p><pre><code><code>WAL + durable vector segments</code></code></pre><p>The ANN index is a <strong>derived structure</strong>.</p><p>Therefore:</p><pre><code><code>Corrupted HNSW
      &#8595;
Delete index
      &#8595;
Rebuild from vector segments</code></code></pre><div><hr></div><h1>17. Microservices</h1><pre><code><code>API Gateway
   &#9474;
   &#9500;&#9472;&#9472; Auth / Rate Limiting
   &#9474;
   &#9660;
Query Service
   &#9474;
   &#9500;&#9472;&#9472; Query Planner
   &#9500;&#9472;&#9472; Filter Engine
   &#9492;&#9472;&#9472; Shard Router
          &#9474;
          &#9660;
      Vector Nodes
       &#9500;&#9472;&#9472; ANN Engine
       &#9500;&#9472;&#9472; Vector Store
       &#9500;&#9472;&#9472; Metadata Store
       &#9492;&#9472;&#9472; WAL Consumer

Write Service
   &#9474;
   &#9500;&#9472;&#9472; Validation
   &#9500;&#9472;&#9472; WAL Producer
   &#9492;&#9472;&#9472; Partition Router

Index Service
   &#9500;&#9472;&#9472; HNSW Builder
   &#9500;&#9472;&#9472; IVF Builder
   &#9500;&#9472;&#9472; PQ Compressor
   &#9492;&#9472;&#9472; Compaction

Metadata Service
   &#9492;&#9472;&#9472; Distributed KV Store

Snapshot Service
   &#9500;&#9472;&#9472; Checkpoint
   &#9492;&#9472;&#9472; Object Storage

Cluster Manager
   &#9500;&#9472;&#9472; Membership
   &#9500;&#9472;&#9472; Leader Election
   &#9500;&#9472;&#9472; Rebalancing
   &#9492;&#9472;&#9472; Health Checks</code></code></pre><div><hr></div><h1>18. Important APIs</h1><h3>Insert</h3><pre><code><code>POST /v1/vectors</code></code></pre><pre><code><code>{
  "id": "vec_123",
  "tenant_id": "tenant_1",
  "embedding": [0.12, 0.43, "..."],
  "metadata": {
    "category": "car",
    "language": "en"
  }
}</code></code></pre><p>Response:</p><pre><code><code>{
  "id": "vec_123",
  "version": 7,
  "status": "accepted"
}</code></code></pre><h3>Search</h3><pre><code><code>POST /v1/search</code></code></pre><pre><code><code>{
  "tenant_id": "tenant_1",
  "query_vector": [0.12, 0.43, "..."],
  "top_k": 20,
  "filter": {
    "category": "car",
    "language": "en"
  }
}</code></code></pre><p>Response:</p><pre><code><code>{
  "results": [
    {
      "id": "vec_892",
      "score": 0.94,
      "metadata": {
        "category": "car"
      }
    }
  ]
}</code></code></pre><h3>Delete</h3><pre><code><code>DELETE /v1/vectors/{id}</code></code></pre><p>Response:</p><pre><code><code>{
  "id": "vec_123",
  "status": "deleted"
}</code></code></pre><div><hr></div><h1>19. Database / Storage Choices</h1><pre><code><code>Vector data
     &#8594; SSD/Object Storage

ANN index
     &#8594; Local NVMe SSD + RAM

Metadata
     &#8594; Cassandra/ScyllaDB or distributed KV

WAL
     &#8594; Kafka

Snapshots
     &#8594; S3/GCS/Object Storage

Cluster metadata
     &#8594; etcd</code></code></pre><p>The important architectural principle is:</p><blockquote><p><strong>Don&#8217;t make the ANN index your source of truth.</strong></p></blockquote><p>Treat vectors + WAL + durable segments as the source of truth and make HNSW/IVF-PQ <strong>rebuildable derived indexes</strong>.</p><div><hr></div><h1>20. Final Architecture</h1><pre><code><code>                         Clients
                            &#9474;
                            &#9660;
                     &#9484;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9488;
                     &#9474; API Gateway &#9474;
                     &#9492;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9516;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9496;
                            &#9474;
                 &#9484;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9524;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9488;
                 &#9660;                     &#9660;
          &#9484;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9488;       &#9484;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9488;
          &#9474; Query Svc   &#9474;       &#9474; Write Svc   &#9474;
          &#9492;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9516;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9496;       &#9492;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9516;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9496;
                 &#9474;                     &#9474;
                 &#9660;                     &#9660;
          &#9484;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9488;          &#9484;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9488;
          &#9474;Query Planner&#9474;          &#9474;  WAL   &#9474;
          &#9492;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9516;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9496;          &#9474; Kafka  &#9474;
                 &#9474;                 &#9492;&#9472;&#9472;&#9472;&#9516;&#9472;&#9472;&#9472;&#9472;&#9496;
                 &#9474;                     &#9474;
                 &#9492;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9516;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9496;
                            &#9660;
                    &#9484;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9488;
                    &#9474; Shard Router  &#9474;
                    &#9492;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9516;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9496;
                            &#9474;
          &#9484;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9532;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9488;
          &#9660;                 &#9660;                 &#9660;
       Shard 1           Shard 2           Shard N
     &#9484;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9488;       &#9484;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9488;       &#9484;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9488;
     &#9474; HNSW    &#9474;       &#9474; IVF-PQ  &#9474;       &#9474; HNSW    &#9474;
     &#9474; Index   &#9474;       &#9474; Index   &#9474;       &#9474; Index   &#9474;
     &#9500;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9508;       &#9500;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9508;       &#9500;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9508;
     &#9474;Vectors  &#9474;       &#9474;Vectors  &#9474;       &#9474;Vectors  &#9474;
     &#9500;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9508;       &#9500;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9508;       &#9500;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9508;
     &#9474;Metadata &#9474;       &#9474;Metadata &#9474;       &#9474;Metadata &#9474;
     &#9492;&#9472;&#9472;&#9472;&#9472;&#9516;&#9472;&#9472;&#9472;&#9472;&#9496;       &#9492;&#9472;&#9472;&#9472;&#9472;&#9516;&#9472;&#9472;&#9472;&#9472;&#9496;       &#9492;&#9472;&#9472;&#9472;&#9472;&#9516;&#9472;&#9472;&#9472;&#9472;&#9496;
          &#9474;                 &#9474;                 &#9474;
          &#9492;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9532;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9496;
                            &#9660;
                     Object Storage
                    Snapshots / Backup</code></code></pre><h3>Key design decisions</h3><ol><li><p><strong>Virtual sharding</strong> enables horizontal scaling to 10B+ vectors.</p></li><li><p><strong>HNSW</strong> is used for hot/recent data where low latency and high recall matter.</p></li><li><p><strong>IVF-PQ</strong> is used for massive cold datasets to reduce memory/storage.</p></li><li><p><strong>Mutable HNSW + immutable segments</strong> enables real-time updates without rebuilding huge indexes.</p></li><li><p><strong>Metadata indexes + adaptive filtering</strong> handle vector + structured queries efficiently.</p></li><li><p><strong>3-way replication across AZs</strong> provides high availability.</p></li><li><p><strong>WAL + snapshots + replay</strong> provides disaster recovery.</p></li><li><p><strong>ANN indexes are derived data</strong>, allowing them to be rebuilt after corruption or failure.</p></li><li><p><strong>Query fan-out + local Top-K + global merge</strong> enables distributed ANN search.</p></li><li><p><strong>Hot/warm/cold tiers</strong> keep the frequently accessed vectors in RAM while cheaply storing billions of older vectors.</p></li></ol>]]></content:encoded></item><item><title><![CDATA[HLD:Design a Multi-Agent Orchestration Platform where planner, researcher, coder, and reviewer agents collaborate. ]]></title><description><![CDATA[Explain workflow scheduling, shared memory, task routing, retries, deadlock prevention, and observability.]]></description><link>https://programmingappliedai.substack.com/p/hlddesign-a-multi-agent-orchestration</link><guid isPermaLink="false">https://programmingappliedai.substack.com/p/hlddesign-a-multi-agent-orchestration</guid><dc:creator><![CDATA[Shashank Mishra]]></dc:creator><pubDate>Mon, 10 Aug 2026 17:30:55 GMT</pubDate><enclosure url="iframe.php?url=https%3A%2F%2Fsubstackcdn.com%2Fimage%2Ffetch%2F%24s_%21riGX%21%2Cw_256%2Cc_limit%2Cf_auto%2Cq_auto%3Agood%2Cfl_progressive%3Asteep%2Fhttps%253A%252F%252Fsubstack-post-media.s3.amazonaws.com%252Fpublic%252Fimages%252F58e132e8-cd28-4037-b0ef-feabb2b68221_144x144.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Below is an interview-ready HLD for a <strong>Multi-Agent Orchestration Platform</strong> where Planner, Researcher, Coder, and Reviewer agents collaborate.</p><p>If you&#8217;re looking for paid 1:1 mentorship with a strong focus on Low-Level Design (LLD)&#8212;especially Multithreading and Concurrency&#8212;along with High-Level Design (HLD), Data Structures &amp; Algorithms (DSA), System Design, LLM/Generative AI systems, and research paper discussions, feel free to reach out.</p><p>The mentorship is tailored for interview preparation, backend engineering, distributed systems, AI infrastructure, and building a strong systems-thinking foundation.</p><p><span>&#128233; Contact: </span><a href="iframe.php?url=mailto%3Aprogrammingappliedai%40gmail.com">programmingappliedai@gmail.com</a></p><h2>1. Functional Requirements &#8212; 5 points</h2><ol><li><p><strong>Task Creation</strong></p><ul><li><p>User should be able to submit a high-level task.</p></li><li><p>Example: <em>&#8220;Build a Python service that analyzes customer transactions.&#8221;</em></p></li></ul></li><li><p><strong>Task Planning</strong></p><ul><li><p>Planner Agent decomposes the task into smaller executable subtasks.</p></li><li><p>Creates dependencies between subtasks.</p></li></ul></li><li><p><strong>Multi-Agent Collaboration</strong></p><ul><li><p>Route subtasks to appropriate agents such as Researcher, Coder, Reviewer, etc.</p></li><li><p>Agents should be able to consume outputs generated by other agents.</p></li></ul></li><li><p><strong>Workflow Execution</strong></p><ul><li><p>Execute independent tasks in parallel and dependent tasks sequentially.</p></li><li><p>Support retries, timeouts, cancellation, and failure handling.</p></li></ul></li><li><p><strong>Monitoring &amp; Results</strong></p><ul><li><p>Track task/agent status, execution history, token usage, latency, failures, and final output.</p></li><li><p>User should be able to query workflow progress and retrieve results.</p></li></ul></li></ol><div><hr></div><h2>2. Non-Functional Requirements &#8212; 5 points</h2><ol><li><p><strong>Scalability</strong></p><ul><li><p>Support thousands/millions of workflows with dynamically scalable agent workers.</p></li></ul></li><li><p><strong>Availability</strong></p><ul><li><p>Target 99.9%+ availability.</p></li><li><p>Agent/workflow failures should not cause loss of workflow state.</p></li></ul></li><li><p><strong>Low Latency</strong></p><ul><li><p>Task scheduling/routing should ideally add &lt;50&#8211;100 ms overhead.</p></li><li><p>Independent agent tasks should execute concurrently.</p></li></ul></li><li><p><strong>Reliability</strong></p><ul><li><p>At-least-once task execution with idempotent workers.</p></li><li><p>Retry transient failures using exponential backoff.</p></li></ul></li><li><p><strong>Observability &amp; Security</strong></p><ul><li><p>Distributed tracing, metrics, logs, token/cost tracking.</p></li><li><p>Tenant-level isolation and authorization for shared memory.</p></li></ul></li></ol><div><hr></div><h1>3. High-Level Architecture</h1><pre><code><code>                         &#9484;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9488;
                         &#9474;      Client      &#9474;
                         &#9474; Web / API / SDK  &#9474;
                         &#9492;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9516;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9496;
                                  &#9474;
                                  &#9660;
                         &#9484;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9488;
                         &#9474;    API Gateway   &#9474;
                         &#9492;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9516;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9496;
                                  &#9474;
                                  &#9660;
                    &#9484;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9488;
                    &#9474;   Workflow Service      &#9474;
                    &#9474;                         &#9474;
                    &#9474; Create / Pause / Resume &#9474;
                    &#9492;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9516;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9496;
                                &#9474;
                                &#9660;
                    &#9484;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9488;
                    &#9474;   Planner Agent         &#9474;
                    &#9474;                         &#9474;
                    &#9474; Task &#8594; DAG of subtasks &#9474;
                    &#9492;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9516;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9496;
                                &#9474;
                                &#9660;
                  &#9484;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9488;
                  &#9474;      Task Scheduler          &#9474;
                  &#9474;                              &#9474;
                  &#9474; DAG + dependency management  &#9474;
                  &#9492;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9516;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9496;
                               &#9474;
                  &#9484;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9532;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9488;
                  &#9660;            &#9660;             &#9660;
             &#9484;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9488;   &#9484;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9488;   &#9484;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9488;
             &#9474;Research&#9474;   &#9474; Coder  &#9474;   &#9474;Reviewer&#9474;
             &#9474; Agent  &#9474;   &#9474; Agent  &#9474;   &#9474; Agent  &#9474;
             &#9492;&#9472;&#9472;&#9472;&#9516;&#9472;&#9472;&#9472;&#9472;&#9496;   &#9492;&#9472;&#9472;&#9472;&#9516;&#9472;&#9472;&#9472;&#9472;&#9496;   &#9492;&#9472;&#9472;&#9472;&#9516;&#9472;&#9472;&#9472;&#9472;&#9496;
                 &#9474;            &#9474;             &#9474;
                 &#9492;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9532;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9496;
                              &#9660;
                    &#9484;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9488;
                    &#9474;   Shared Memory    &#9474;
                    &#9474;                    &#9474;
                    &#9474; Context / Artifacts&#9474;
                    &#9474; Agent Outputs      &#9474;
                    &#9492;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9496;

                              &#9474;
                              &#9660;
                    &#9484;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9488;
                    &#9474;   Event Bus        &#9474;
                    &#9474; Kafka / SQS        &#9474;
                    &#9492;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9496;

                              &#9474;
                              &#9660;
                    &#9484;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9488;
                    &#9474; Observability      &#9474;
                    &#9474; Metrics / Logs /   &#9474;
                    &#9474; Traces / Cost      &#9474;
                    &#9492;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9496;
</code></code></pre><div><hr></div><h1>4. Core Workflow</h1><p>Suppose the user asks:</p><blockquote><p>&#8220;Build a REST API for analyzing transactions.&#8221;</p></blockquote><p>Planner creates:</p><pre><code><code>                Root Task
                   &#9474;
          &#9484;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9524;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9488;
          &#9660;                 &#9660;
   Research APIs       Research DB
          &#9474;                 &#9474;
          &#9492;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9516;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9496;
                   &#9660;
              Write Code
                   &#9474;
                   &#9660;
             Run Tests
                   &#9474;
                   &#9660;
                Review
                   &#9474;
             &#9484;&#9472;&#9472;&#9472;&#9472;&#9472;&#9524;&#9472;&#9472;&#9472;&#9472;&#9472;&#9488;
             &#9474;           &#9474;
           PASS         FAIL
             &#9474;           &#9474;
             &#9660;           &#9660;
           Done       Fix Code
                         &#9474;
                         &#9492;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#8594; Review
</code></code></pre><p>The workflow is represented as a <strong>DAG</strong>.</p><p>Each node contains:</p><pre><code><code>Task {
    task_id
    workflow_id
    agent_type
    input
    dependencies[]
    status
    retry_count
    timeout
}
</code></code></pre><div><hr></div><h1>5. Task Scheduling</h1><p>The <strong>Task Scheduler</strong> maintains the workflow DAG.</p><h3>Task lifecycle</h3><pre><code><code>PENDING
   &#8595;
READY
   &#8595;
RUNNING
   &#8595;
SUCCESS
</code></code></pre><p>Failure:</p><pre><code><code>RUNNING
   &#8595;
FAILED
   &#8595;
RETRY
   &#8595;
READY
</code></code></pre><p>After maximum retries:</p><pre><code><code>FAILED &#8594; DEAD_LETTER
</code></code></pre><h3>Scheduling algorithm</h3><p>For every completed task:</p><pre><code><code>1. Mark task SUCCESS
2. Find dependent tasks
3. Check whether all dependencies are SUCCESS
4. If yes &#8594; mark dependent task READY
5. Push task to appropriate agent queue
</code></code></pre><p>Independent tasks can therefore execute concurrently.</p><div><hr></div><h1>6. Task Routing</h1><p>Use an <strong>Agent Registry</strong>.</p><pre><code><code>Agent Registry

researcher &#8594; researcher_queue
coder      &#8594; coder_queue
reviewer   &#8594; reviewer_queue
planner    &#8594; planner_queue
</code></code></pre><p>Scheduler determines:</p><pre><code><code>task.agent_type = CODER
</code></code></pre><p>and publishes:</p><pre><code><code>Kafka:
    topic = agent.coder.tasks
</code></code></pre><p>Coder workers consume from this topic.</p><p>For dynamic routing, maintain agent metadata:</p><pre><code><code>Agent {
    agent_id
    type
    capabilities[]
    current_load
    max_concurrency
    health
}
</code></code></pre><p>Example:</p><pre><code><code>"Search latest Kafka documentation"
            &#8595;
Researcher
            &#8595;
Researcher-3
</code></code></pre><p>Routing can consider:</p><ul><li><p>capability</p></li><li><p>current load</p></li><li><p>priority</p></li><li><p>model availability</p></li><li><p>cost</p></li><li><p>region</p></li></ul><div><hr></div><h1>7. Shared Memory</h1><p>Agents shouldn&#8217;t directly depend on each other&#8217;s local memory.</p><p>Use a centralized <strong>Shared Memory Service</strong>.</p><pre><code><code>                     Shared Memory
                          &#9474;
        &#9484;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9532;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9488;
        &#9474;                 &#9474;                 &#9474;
    Task Context       Artifacts        Agent Outputs
        &#9474;                 &#9474;                 &#9474;
    Redis/Postgres    Object Storage    Vector DB
</code></code></pre><h3>Types of memory</h3><p><strong>Short-term memory</strong></p><p>Current workflow context.</p><pre><code><code>Redis
</code></code></pre><p><strong>Durable state</strong></p><p>Workflow/task state.</p><pre><code><code>PostgreSQL
</code></code></pre><p><strong>Large artifacts</strong></p><p>Code, documents, datasets.</p><pre><code><code>S3 / Object Storage
</code></code></pre><p><strong>Semantic memory</strong></p><p>Research findings, previous knowledge.</p><pre><code><code>Vector DB
</code></code></pre><p>Agents access memory using:</p><pre><code><code>GET /workflows/{workflow_id}/context
</code></code></pre><p>and:</p><pre><code><code>POST /workflows/{workflow_id}/memory
</code></code></pre><div><hr></div><h1>8. Retry Strategy</h1><p>Not every failure should be retried.</p><h3>Retryable</h3><pre><code><code>LLM timeout
Network failure
Rate limit
Temporary DB failure
Temporary service unavailable
</code></code></pre><h3>Non-retryable</h3><pre><code><code>Invalid prompt
Invalid tool arguments
Permission denied
Invalid workflow
</code></code></pre><p>Use exponential backoff:</p><pre><code><code>retry 1 &#8594; 1 sec
retry 2 &#8594; 2 sec
retry 3 &#8594; 4 sec
retry 4 &#8594; 8 sec
</code></code></pre><p>with jitter.</p><p>Each task has:</p><pre><code><code>max_retries = 3
</code></code></pre><p>After that:</p><pre><code><code>Dead Letter Queue
</code></code></pre><div><hr></div><h1>9. Deadlock Prevention</h1><p>Since workflows are DAG-based, the system should <strong>reject cyclic dependencies</strong>.</p><p>Example invalid workflow:</p><pre><code><code>A &#8594; B
B &#8594; C
C &#8594; A
</code></code></pre><p>When creating the DAG, perform cycle detection using:</p><pre><code><code>DFS / Topological Sort
</code></code></pre><p>If:</p><pre><code><code>number_of_processed_nodes != total_nodes
</code></code></pre><p>then a cycle exists.</p><p>Return:</p><pre><code><code>400 INVALID_WORKFLOW
</code></code></pre><h3>Runtime deadlock prevention</h3><p>Also use:</p><ul><li><p>Task timeout</p></li><li><p>Workflow timeout</p></li><li><p>Lease expiration</p></li><li><p>Heartbeats</p></li><li><p>Maximum dependency depth</p></li><li><p>Maximum task execution time</p></li><li><p>Cancellation propagation</p></li></ul><p>Example:</p><pre><code><code>Worker takes task
      &#8595;
Lease = 5 minutes
      &#8595;
Worker sends heartbeat
      &#8595;
Worker crashes
      &#8595;
Lease expires
      &#8595;
Scheduler requeues task
</code></code></pre><div><hr></div><h1>10. APIs</h1><h2>Create Workflow</h2><pre><code><code>POST /v1/workflows
</code></code></pre><h3>Request</h3><pre><code><code>{
  "task": "Build a REST API for analyzing customer transactions",
  "priority": "HIGH",
  "max_retries": 3,
  "metadata": {
    "language": "python"
  }
}
</code></code></pre><h3>Response</h3><pre><code><code>{
  "workflow_id": "wf_12345",
  "status": "PLANNING",
  "created_at": "2026-08-10T17:00:00Z"
}
</code></code></pre><div><hr></div><h2>Get Workflow Status</h2><pre><code><code>GET /v1/workflows/{workflow_id}
</code></code></pre><h3>Response</h3><pre><code><code>{
  "workflow_id": "wf_12345",
  "status": "RUNNING",
  "progress": 65,
  "tasks": [
    {
      "task_id": "t1",
      "agent": "researcher",
      "status": "SUCCESS"
    },
    {
      "task_id": "t2",
      "agent": "coder",
      "status": "RUNNING"
    },
    {
      "task_id": "t3",
      "agent": "reviewer",
      "status": "PENDING"
    }
  ]
}
</code></code></pre><div><hr></div><h2>Get Workflow Result</h2><pre><code><code>GET /v1/workflows/{workflow_id}/result
</code></code></pre><h3>Response</h3><pre><code><code>{
  "workflow_id": "wf_12345",
  "status": "COMPLETED",
  "result": {
    "code_artifact": "s3://bucket/code.zip",
    "review": "Approved",
    "summary": "REST API implemented successfully"
  }
}
</code></code></pre><div><hr></div><h2>Cancel Workflow</h2><pre><code><code>POST /v1/workflows/{workflow_id}/cancel
</code></code></pre><h3>Response</h3><pre><code><code>{
  "workflow_id": "wf_12345",
  "status": "CANCELLED"
}
</code></code></pre><div><hr></div><h2>Get Shared Memory</h2><pre><code><code>GET /v1/workflows/{workflow_id}/memory
</code></code></pre><h3>Response</h3><pre><code><code>{
  "workflow_id": "wf_12345",
  "memory": [
    {
      "task_id": "t1",
      "type": "RESEARCH_RESULT",
      "content": "PostgreSQL is selected as the primary database"
    },
    {
      "task_id": "t2",
      "type": "CODE_ARTIFACT",
      "uri": "s3://bucket/code.zip"
    }
  ]
}
</code></code></pre><div><hr></div><h1>11. Microservices Architecture</h1><h3>1. API Gateway</h3><p>Responsibilities:</p><pre><code><code>Authentication
Authorization
Rate limiting
Request validation
Routing
</code></code></pre><div><hr></div><h3>2. Workflow Service</h3><p>Responsible for:</p><pre><code><code>Create workflow
Pause/resume
Cancel workflow
Workflow state
</code></code></pre><div><hr></div><h3>3. Planner Service</h3><p>Converts:</p><pre><code><code>User Goal
   &#8595;
Task DAG
</code></code></pre><p>Example:</p><pre><code><code>Research &#8594; Code &#8594; Test &#8594; Review
</code></code></pre><div><hr></div><h3>4. Scheduler Service</h3><p>Responsible for:</p><pre><code><code>DAG execution
Dependency resolution
Task prioritization
Retries
Timeouts
Task leases
</code></code></pre><div><hr></div><h3>5. Agent Router</h3><p>Routes tasks based on:</p><pre><code><code>Agent type
Capability
Load
Cost
Model
Availability
</code></code></pre><div><hr></div><h3>6. Agent Workers</h3><p>Separate worker pools:</p><pre><code><code>Researcher Workers
Coder Workers
Reviewer Workers
Planner Workers
</code></code></pre><p>Each worker can independently scale.</p><div><hr></div><h3>7. Memory Service</h3><p>Provides:</p><pre><code><code>Read context
Write context
Semantic search
Artifact references
Versioning
</code></code></pre><div><hr></div><h3>8. Artifact Service</h3><p>Stores:</p><pre><code><code>Source code
Documents
Research reports
Images
Large outputs
</code></code></pre><p>Object storage such as S3 is appropriate.</p><div><hr></div><h3>9. Event Bus</h3><p>Kafka/SQS handles:</p><pre><code><code>Task created
Task completed
Task failed
Retry task
Workflow completed
Agent events
</code></code></pre><div><hr></div><h3>10. Observability Service</h3><p>Collect:</p><pre><code><code>Metrics
Logs
Distributed traces
LLM token usage
LLM cost
Agent latency
Task retry count
Workflow success rate
</code></code></pre><div><hr></div><h1>12. Database Choice</h1><div class="highlighted_code_block" data-attrs="{&quot;language&quot;:&quot;plaintext&quot;,&quot;nodeId&quot;:&quot;21f28340-c702-4b27-beda-079ca23a9f7a&quot;}" data-component-name="HighlightedCodeBlockToDOM"><pre class="shiki"><code class="language-plaintext">| Data                | Database                 | Why                                    |
| ------------------- | ------------------------ | -------------------------------------- |
| Workflow/Task state | PostgreSQL               | Transactions + relational DAG metadata |
| Hot workflow state  | Redis                    | Low-latency reads/writes               |
| Agent queues/events | Kafka                    | Durable asynchronous processing        |
| Large artifacts     | S3/Object Storage        | Cheap, scalable blob storage           |
| Semantic memory     | Vector DB                | Similarity search                      |
| Logs                | ClickHouse/Elasticsearch | High-volume analytics/search           |
</code></pre></div><h3>PostgreSQL Schema</h3><pre><code><code>workflows
---------
workflow_id PK
tenant_id
status
priority
input
created_at
updated_at


tasks
-----
task_id PK
workflow_id FK
agent_type
status
input
output
retry_count
max_retries
timeout
created_at
updated_at


task_dependencies
-----------------
task_id
depends_on_task_id
PRIMARY KEY(task_id, depends_on_task_id)


agent_executions
----------------
execution_id PK
task_id
agent_id
started_at
completed_at
status
error
token_usage
cost
</code></code></pre><div><hr></div><h1>13. Important Design Decision: DB + Kafka</h1><p>Don&#8217;t use Kafka as the source of truth for workflow state.</p><p>Use:</p><pre><code><code>PostgreSQL = Source of Truth
Kafka      = Event/Task Transport
Redis      = Cache
</code></code></pre><p>For example:</p><pre><code><code>Task completed
     &#9474;
     &#9500;&#9472;&#9472; UPDATE PostgreSQL
     &#9474;
     &#9492;&#9472;&#9472; Publish TaskCompleted event &#8594; Kafka
</code></code></pre><p>For reliable DB &#8594; Kafka publishing, use the <strong>Transactional Outbox Pattern</strong>:</p><pre><code><code>                    PostgreSQL
                 &#9484;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9488;
                 &#9474; task update &#9474;
                 &#9474; outbox event&#9474;
                 &#9492;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9516;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9496;
                        &#9474;
                  Outbox Worker
                        &#9474;
                        &#9660;
                      Kafka
</code></code></pre><p>This prevents the situation where the DB update succeeds but the Kafka event is lost.</p><div><hr></div><h1>14. End-to-End Flow</h1><pre><code><code>User
 &#9474;
 &#9660;
API Gateway
 &#9474;
 &#9660;
Workflow Service
 &#9474;
 &#9660;
Planner Agent
 &#9474;
 &#9474; Creates DAG
 &#9660;
Task Scheduler
 &#9474;
 &#9500;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9488;
 &#9660;              &#9660;
Researcher     Researcher
 &#9474;              &#9474;
 &#9492;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9516;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9496;
        &#9660;
      Coder
        &#9474;
        &#9660;
      Tests
        &#9474;
        &#9660;
     Reviewer
        &#9474;
    &#9484;&#9472;&#9472;&#9472;&#9524;&#9472;&#9472;&#9472;&#9488;
    &#9474;       &#9474;
  PASS     FAIL
    &#9474;       &#9474;
    &#9660;       &#9660;
  Done    Coder
            &#9474;
            &#9492;&#9472;&#9472;&#9472;&#9472;&#8594; Reviewer
</code></code></pre><p>Every agent interaction is recorded in:</p><pre><code><code>PostgreSQL &#8594; workflow/task state
Redis      &#8594; hot context
Kafka      &#8594; events/tasks
S3        &#8594; artifacts
Vector DB  &#8594; semantic memory
</code></code></pre><p>And monitored through:</p><pre><code><code>OpenTelemetry
      &#8595;
Metrics + Logs + Traces
      &#8595;
Grafana / Alerting
</code></code></pre><p><strong>Key interview point:</strong> The heart of this system is a <strong>persistent DAG-based workflow engine + asynchronous task queues + shared memory layer</strong>. The agents themselves remain stateless workers, which makes them independently scalable and allows the scheduler to handle retries, failures, timeouts, and recovery centrally.</p>]]></content:encoded></item><item><title><![CDATA[ [HLD]: Distributed Prompt Cache for LLM Cost Optimization]]></title><description><![CDATA[Multiple applications (chatbots, support assistants, coding assistants, search copilots, etc.) send repeated or similar prompts to LLM providers. Since LLM inference is expensive .]]></description><link>https://programmingappliedai.substack.com/p/hld-distributed-prompt-cache-for</link><guid isPermaLink="false">https://programmingappliedai.substack.com/p/hld-distributed-prompt-cache-for</guid><dc:creator><![CDATA[Shashank Mishra]]></dc:creator><pubDate>Tue, 04 Aug 2026 15:11:51 GMT</pubDate><enclosure url="iframe.php?url=https%3A%2F%2Fsubstackcdn.com%2Fimage%2Ffetch%2F%24s_%21riGX%21%2Cw_256%2Cc_limit%2Cf_auto%2Cq_auto%3Agood%2Cfl_progressive%3Asteep%2Fhttps%253A%252F%252Fsubstack-post-media.s3.amazonaws.com%252Fpublic%252Fimages%252F58e132e8-cd28-4037-b0ef-feabb2b68221_144x144.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2>1. Problem Statement</h2><p>Multiple applications (chatbots, support assistants, coding assistants, search copilots, etc.) send repeated or similar prompts to LLM providers. Since LLM inference is expensive and introduces latency, we need a <strong>Distributed Prompt Cache</strong> that:</p><ul><li><p>Reduces LLM API costs</p></li><li><p>Reduces response latency</p></li><li><p>Supports multiple applications and tenants</p></li><li><p>Handles exact and semantic prompt matching</p></li><li><p>Preserves privacy and security</p></li><li><p>Scales horizontally</p></li></ul><div><hr></div><h1>2. Functional Requirements</h1><h3>Core Features</h3><ul><li><p>Cache LLM responses for repeated prompts</p></li><li><p>Support exact-match lookup</p></li><li><p>Support semantic similarity lookup</p></li><li><p>Configurable TTL policies</p></li><li><p>Cache invalidation support</p></li><li><p>Multi-tenant isolation</p></li><li><p>Cache warming/pre-population</p></li><li><p>Distributed deployment</p></li></ul><h3>Non-Functional Requirements</h3><ul><li><p>High availability (99.9%+)</p></li><li><p>Low latency (&lt;20 ms cache lookup)</p></li><li><p>Horizontally scalable</p></li><li><p>Secure tenant isolation</p></li><li><p>Cost-efficient storage</p></li></ul><div><hr></div><h1>3. High-Level Architecture</h1><pre><code><code>                +----------------+
                | Applications   |
                | (Multi-tenant) |
                +-------+--------+
                        |
                        v
           +-------------------------+
           | Prompt Cache Gateway    |
           +-----------+-------------+
                       |
         +-------------+--------------+
         |                            |
         v                            v

+----------------+        +---------------------+
| Exact Cache    |        | Semantic Cache      |
| (Redis)        |        | (Vector DB)         |
+--------+-------+        +----------+----------+
         |                           |
         +------------+--------------+
                      |
                      v
            +------------------+
            | Cache Decision   |
            | Service          |
            +--------+---------+
                     |
          Cache Miss |
                     v
             +---------------+
             | LLM Provider  |
             | (GPT/Claude)  |
             +-------+-------+
                     |
                     v
             +---------------+
             | Cache Writer  |
             +---------------+
</code></code></pre><div><hr></div><h1>4. Request Flow</h1><h3>Exact Match Hit</h3><pre><code><code>User Request
      |
      v
Generate Cache Key
      |
      v
Redis Lookup
      |
      +---- HIT ----&gt; Return Response
</code></code></pre><h3>Cache Miss</h3><pre><code><code>User Request
      |
      v
Exact Match Lookup
      |
      +---- MISS
               |
               v
       Semantic Search
               |
         Similarity &gt; Threshold?
             /        \
           Yes        No
            |          |
            v          v
      Return Cached   Call LLM
       Response         |
                         v
                  Store in Cache
</code></code></pre><div><hr></div><h1>5. Cache Key Design</h1><p>The cache key must uniquely identify prompts that should produce identical responses.</p><h3>Key Structure</h3><pre><code><code>hash(
    tenant_id +
    model_name +
    model_version +
    system_prompt +
    user_prompt +
    temperature +
    top_p
)
</code></code></pre><h3>Example</h3><pre><code><code>tenantA:gpt-4o:v2:
SHA256(normalized_prompt)
</code></code></pre><h3>Why Include These Fields?</h3><div class="highlighted_code_block" data-attrs="{&quot;language&quot;:&quot;plaintext&quot;,&quot;nodeId&quot;:&quot;cfd61b0c-8a35-44f7-b204-f2e86d7eacbe&quot;}" data-component-name="HighlightedCodeBlockToDOM"><pre class="shiki"><code class="language-plaintext">| Field         | Reason                                     |
| ------------- | ------------------------------------------ |
| Tenant ID     | Prevent data leakage                       |
| Model Name    | Different models produce different outputs |
| Model Version | Responses change after upgrades            |
| Temperature   | Affects output randomness                  |
| System Prompt | Changes behavior                           |
| User Prompt   | Main query                                 |
</code></pre></div><div><hr></div><h1>6. Prompt Normalization</h1><p>Before generating cache keys:</p><h3>Transformations</h3><pre><code><code>" What is Kubernetes? "
"What is Kubernetes?"
</code></code></pre><p>Normalize:</p><ul><li><p>Trim whitespace</p></li><li><p>Lowercase (optional)</p></li><li><p>Remove repeated spaces</p></li><li><p>Canonicalize formatting</p></li></ul><p>Example:</p><pre><code><code>"What  is Kubernetes?"
</code></code></pre><p>&#8595;</p><pre><code><code>"what is kubernetes?"
</code></code></pre><p>This improves cache hit rates.</p><div><hr></div><h1>7. Semantic Similarity Matching</h1><p>Exact matching misses logically equivalent prompts.</p><h3>Examples</h3><p>Prompt A:</p><pre><code><code>What is Kubernetes?
</code></code></pre><p>Prompt B:</p><pre><code><code>Explain Kubernetes.
</code></code></pre><p>Both should reuse the same response.</p><div><hr></div><h2>Semantic Cache Architecture</h2><h3>Step 1: Generate Embedding</h3><pre><code><code>Prompt
   |
Embedding Model
   |
Vector (1536 dimensions)
</code></code></pre><h3>Step 2: Store in Vector DB</h3><p>Possible technologies:</p><ul><li><p>Pinecone</p></li><li><p>Weaviate</p></li><li><p>Milvus</p></li><li><p>pgvector</p></li><li><p>OpenSearch Vector Search</p></li></ul><p>Store:</p><pre><code><code>{
  "tenant":"A",
  "embedding":[...],
  "response":"...",
  "ttl":"..."
}
</code></code></pre><div><hr></div><h2>Lookup</h2><pre><code><code>New Prompt
      |
Generate Embedding
      |
Vector Search
      |
Top K Results
      |
Similarity Score
</code></code></pre><h3>Decision Rule</h3><pre><code><code>similarity &gt;= 0.92
</code></code></pre><p>&#8594; Cache Hit</p><p>Else</p><p>&#8594; LLM Call</p><h3>Similarity Metrics</h3><ul><li><p>Cosine similarity</p></li><li><p>Euclidean distance</p></li><li><p>Dot product</p></li></ul><p>Cosine similarity is most common.</p><div><hr></div><h1>8. Cache Storage Design</h1><h2>L1 Cache</h2><p>Redis</p><p>Purpose:</p><ul><li><p>Ultra-fast exact lookup</p></li><li><p>Millisecond latency</p></li></ul><p>Stores:</p><pre><code><code>key -&gt; response
</code></code></pre><div><hr></div><h2>L2 Cache</h2><p>Vector Database</p><p>Purpose:</p><ul><li><p>Semantic retrieval</p></li></ul><p>Stores:</p><pre><code><code>embedding -&gt; response
</code></code></pre><div><hr></div><h1>9. TTL Strategy</h1><p>Not all prompts age equally.</p><h3>Dynamic TTL</h3><div class="highlighted_code_block" data-attrs="{&quot;language&quot;:&quot;plaintext&quot;,&quot;nodeId&quot;:&quot;0b13e4c2-4cba-43f7-95eb-2b3131a47e7a&quot;}" data-component-name="HighlightedCodeBlockToDOM"><pre class="shiki"><code class="language-plaintext">| Prompt Type  | TTL     |
| ------------ | ------- |
| Math         | 30 days |
| Coding Help  | 7 days  |
| News         | 1 hour  |
| Weather      | 15 mins |
| Stock Prices | 5 mins  |
</code></pre></div><div><hr></div><h3>TTL Formula</h3><pre><code><code>TTL =
baseTTL *
accessFrequencyMultiplier *
confidenceMultiplier
</code></code></pre><p>Frequently reused prompts stay longer.</p><div><hr></div><h1>10. Cache Invalidation</h1><p>One of the hardest problems.</p><h2>Trigger 1: Model Upgrade</h2><pre><code><code>GPT-4o-v1
      &#8595;
GPT-4o-v2
</code></code></pre><p>Invalidate entries tied to old version.</p><div><hr></div><h2>Trigger 2: Prompt Template Change</h2><pre><code><code>System Prompt Changed
</code></code></pre><p>Invalidate matching namespace.</p><div><hr></div><h2>Trigger 3: Knowledge Refresh</h2><p>Example:</p><pre><code><code>Company policy updated
</code></code></pre><p>Invalidate related cache entries.</p><div><hr></div><h2>Trigger 4: Manual Purge</h2><p>Admin API:</p><pre><code><code>DELETE /cache/{tenant}
DELETE /cache/key/{id}
</code></code></pre><div><hr></div><h1>11. Privacy Isolation</h1><p>Critical in enterprise environments.</p><h2>Tenant Isolation</h2><p>Every cache entry contains:</p><pre><code><code>tenant_id
</code></code></pre><p>Lookup only within same tenant.</p><pre><code><code>tenantA &#8800; tenantB
</code></code></pre><p>No cross-tenant reuse.</p><div><hr></div><h2>Namespace Isolation</h2><pre><code><code>tenantA/app1
tenantA/app2
tenantB/app1
</code></code></pre><p>Separate cache namespaces.</p><div><hr></div><h2>Encryption</h2><p>At Rest:</p><ul><li><p>AES-256</p></li></ul><p>In Transit:</p><ul><li><p>TLS</p></li></ul><div><hr></div><h2>Sensitive Data Protection</h2><p>Before caching:</p><pre><code><code>Prompt
   |
PII Detector
   |
Sensitive?
</code></code></pre><p>If sensitive:</p><pre><code><code>Do Not Cache
</code></code></pre><p>Examples:</p><ul><li><p>Credit card numbers</p></li><li><p>SSN</p></li><li><p>Passwords</p></li><li><p>Medical records</p></li></ul><div><hr></div><h1>12. Cache Warming</h1><p>Pre-populate cache before traffic arrives.</p><h2>Method 1: Historical Analysis</h2><p>Use top prompts from logs.</p><pre><code><code>Top 10,000 prompts
      |
Generate Responses
      |
Populate Cache
</code></code></pre><div><hr></div><h2>Method 2: Product Launch Warmup</h2><p>Example:</p><pre><code><code>New HR Bot
</code></code></pre><p>Preload:</p><ul><li><p>Leave policy</p></li><li><p>Benefits</p></li><li><p>Payroll FAQ</p></li></ul><div><hr></div><h2>Method 3: Scheduled Refresh</h2><p>Nightly job:</p><pre><code><code>Refresh frequently used entries
</code></code></pre><p>before expiry.</p><div><hr></div><h1>13. Scalability Design</h1><h3>Redis Cluster</h3><pre><code><code>Redis Shard 1
Redis Shard 2
Redis Shard 3
</code></code></pre><p>Partition by:</p><pre><code><code>hash(cache_key)
</code></code></pre><div><hr></div><h3>Vector DB Cluster</h3><pre><code><code>Embedding Space
      |
Partition/Sharding
      |
Multiple Nodes
</code></code></pre><p>Supports billions of vectors.</p><div><hr></div><h1>14. APIs</h1><h3>Lookup</h3><pre><code><code>POST /cache/lookup
</code></code></pre><p>Request:</p><pre><code><code>{
  "tenant":"A",
  "prompt":"What is Kubernetes?"
}
</code></code></pre><p>Response:</p><pre><code><code>{
  "hit": true,
  "response":"..."
}
</code></code></pre><div><hr></div><h3>Insert</h3><pre><code><code>POST /cache/store
</code></code></pre><div><hr></div><h3>Invalidate</h3><pre><code><code>DELETE /cache/key/{id}
</code></code></pre><div><hr></div><h1>15. Metrics &amp; Monitoring</h1><p>Track:</p><h3>Cache Metrics</h3><pre><code><code>Exact Hit Rate
Semantic Hit Rate
Miss Rate
</code></code></pre><h3>Cost Metrics</h3><pre><code><code>Tokens Saved
LLM Calls Avoided
Dollar Savings
</code></code></pre><h3>Performance Metrics</h3><pre><code><code>P95 Latency
P99 Latency
Redis Latency
Vector Search Latency
</code></code></pre><div><hr></div><h1>16. Design Decisions Summary</h1><div class="highlighted_code_block" data-attrs="{&quot;language&quot;:&quot;plaintext&quot;,&quot;nodeId&quot;:&quot;40f5e8b2-3498-488f-b734-96a1f5713e6c&quot;}" data-component-name="HighlightedCodeBlockToDOM"><pre class="shiki"><code class="language-plaintext">| Component         | Choice                                 |
| ----------------- | -------------------------------------- |
| L1 Cache          | Redis Cluster                          |
| L2 Semantic Cache | Vector DB (Milvus/Pinecone/pgvector)   |
| Cache Key         | Hash(tenant + model + prompt config)   |
| Similarity Metric | Cosine Similarity                      |
| Threshold         | 0.90&#8211;0.95                              |
| TTL               | Dynamic by content type                |
| Invalidation      | Versioning + Event-driven purge        |
| Privacy           | Tenant namespaces + PII filtering      |
| Warming           | Historical prompts + scheduled refresh |
</code></pre></div><h2>Final Design</h2><p>A <strong>two-level distributed prompt cache</strong> consists of:</p><ol><li><p><strong>L1 Redis exact-match cache</strong> for sub-millisecond retrieval.</p></li><li><p><strong>L2 Vector semantic cache</strong> for similar prompts.</p></li><li><p><strong>Tenant-aware cache keys</strong> for privacy.</p></li><li><p><strong>Dynamic TTL and invalidation policies</strong> to maintain freshness.</p></li><li><p><strong>Cache warming pipelines</strong> to maximize hit rates.</p></li><li><p><strong>Horizontal scaling via Redis Cluster and distributed vector databases</strong>.</p></li></ol><p>This architecture can typically reduce <strong>30&#8211;70% of LLM calls</strong>, significantly lowering inference costs and improving response latency across multiple applications.</p>]]></content:encoded></item><item><title><![CDATA[Design a Voice AI Agent supporting 10 million concurrent users with <300ms latency. ]]></title><description><![CDATA[Will discuss streaming ASR, LLM inference, TTS, session management, interruption handling (barge-in), autoscaling, and GPU utilization.]]></description><link>https://programmingappliedai.substack.com/p/design-a-voice-ai-agent-supporting</link><guid isPermaLink="false">https://programmingappliedai.substack.com/p/design-a-voice-ai-agent-supporting</guid><dc:creator><![CDATA[Shashank Mishra]]></dc:creator><pubDate>Fri, 31 Jul 2026 16:17:19 GMT</pubDate><enclosure url="iframe.php?url=https%3A%2F%2Fsubstackcdn.com%2Fimage%2Ffetch%2F%24s_%21riGX%21%2Cw_256%2Cc_limit%2Cf_auto%2Cq_auto%3Agood%2Cfl_progressive%3Asteep%2Fhttps%253A%252F%252Fsubstack-post-media.s3.amazonaws.com%252Fpublic%252Fimages%252F58e132e8-cd28-4037-b0ef-feabb2b68221_144x144.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p></p><p>If you&#8217;re looking for paid 1:1 mentorship with a strong focus on Low-Level Design (LLD)&#8212;especially Multithreading and Concurrency&#8212;along with High-Level Design (HLD), Data Structures &amp; Algorithms (DSA), System Design, LLM/Generative AI systems, and research paper discussions, feel free to reach out.</p><p>The mentorship is tailored for interview preparation, backend engineering, distributed systems, AI infrastructure, and building a strong systems-thinking foundation.</p><p>&#128233; Contact: <a href="iframe.php?url=mailto%3Aprogrammingappliedai%40gmail.com">programmingappliedai@gmail.com</a></p><h1>Functional Requirements (FR)</h1><ul><li><p>Users should be able to interact with the AI agent using voice in real time.</p></li><li><p>System should convert speech to text (ASR), generate responses using an LLM, and convert responses back to speech (TTS).</p></li><li><p>System should support full-duplex conversations where users can interrupt the AI while it is speaking (barge-in).</p></li><li><p>System should maintain conversational context and session history across multiple turns.</p></li><li><p>System should support multilingual conversations and voice personalization.</p></li></ul><div><hr></div><h1>Non-Functional Requirements (NFR)</h1><ul><li><p>Support up to <strong>10 million concurrent users</strong> globally.</p></li><li><p>End-to-end voice response latency should be <strong>less than 300 ms</strong>.</p></li><li><p>Achieve <strong>99.99% availability</strong> with no single point of failure.</p></li><li><p>Scale horizontally across regions with automatic failover.</p></li><li><p>Optimize GPU utilization to maximize throughput and minimize inference costs.</p></li></ul><div><hr></div><h1>Capacity Estimation</h1><p>Assumptions:</p><ul><li><p>10M concurrent users.</p></li><li><p>Average audio packet every 100 ms.</p></li><li><p>Average audio chunk size = 3 KB.</p></li></ul><p>Incoming traffic:</p><pre><code><code>10M &#215; 10 chunks/sec
=
100M audio chunks/sec
</code></code></pre><p>Bandwidth:</p><pre><code><code>100M &#215; 3 KB
=
300 GB/sec
</code></code></pre><p>This requires a globally distributed architecture with edge processing.</p><div><hr></div><h1>Core APIs</h1><h2>Start Session</h2><h3>Request</h3><pre><code><code>POST /v1/session/start
</code></code></pre><pre><code><code>{
  "userId": "u123",
  "language": "en",
  "voice": "female_1"
}
</code></code></pre><h3>Response</h3><pre><code><code>{
  "sessionId": "sess_789",
  "websocketUrl": "wss://voice.company.com/session/sess_789"
}
</code></code></pre><div><hr></div><h2>Streaming Audio API</h2><h3>WebSocket</h3><pre><code><code>wss://voice.company.com/session/{sessionId}
</code></code></pre><p>Client continuously sends audio chunks.</p><pre><code><code>{
  "sequence": 1,
  "audioChunk": "&lt;binary&gt;"
}
</code></code></pre><div><hr></div><h2>Session End API</h2><pre><code><code>POST /v1/session/end
</code></code></pre><pre><code><code>{
  "sessionId": "sess_789"
}
</code></code></pre><div><hr></div><h2>Health API</h2><pre><code><code>GET /v1/health
</code></code></pre><div><hr></div><h1>High-Level Components / Microservices</h1><ul><li><p>API Gateway</p></li><li><p>WebSocket Gateway</p></li><li><p>Session Management Service</p></li><li><p>Streaming ASR Service</p></li><li><p>Conversation Orchestrator</p></li><li><p>Context/Memory Service</p></li><li><p>LLM Inference Service</p></li><li><p>TTS Service</p></li><li><p>Barge-In Detection Service</p></li><li><p>GPU Scheduler</p></li><li><p>Model Serving Platform</p></li><li><p>Redis Session Cache</p></li><li><p>Kafka/Pulsar Event Bus</p></li><li><p>Monitoring &amp; Analytics Service</p></li></ul><div><hr></div><h1>Database Schema</h1><h2>Session Table</h2><pre><code><code>CREATE TABLE sessions (
    session_id VARCHAR(128) PRIMARY KEY,
    user_id VARCHAR(128),
    status VARCHAR(32),
    started_at TIMESTAMP,
    last_activity TIMESTAMP
);
</code></code></pre><div><hr></div><h2>Conversation History</h2><pre><code><code>CREATE TABLE conversations (
    id BIGSERIAL PRIMARY KEY,
    session_id VARCHAR(128),
    role VARCHAR(16),
    message TEXT,
    created_at TIMESTAMP
);
</code></code></pre><div><hr></div><h2>User Voice Preferences</h2><pre><code><code>CREATE TABLE voice_profiles (
    user_id VARCHAR(128) PRIMARY KEY,
    language VARCHAR(32),
    preferred_voice VARCHAR(64)
);
</code></code></pre><div><hr></div><h1>Microservices Interaction</h1><h2>Step 1: User Starts Conversation</h2><p>User opens application.</p><p>Request reaches API Gateway.</p><p>API Gateway forwards request to Session Service.</p><p>Session Service:</p><ul><li><p>Creates session.</p></li><li><p>Allocates region.</p></li><li><p>Stores metadata in Redis.</p></li></ul><p>Returns WebSocket endpoint.</p><div><hr></div><h2>Step 2: User Starts Speaking</h2><p>Audio stream arrives through WebSocket Gateway.</p><p>Gateway forwards chunks to Streaming ASR Service.</p><p>Example:</p><pre><code><code>User:
"Book me a flight to London"
</code></code></pre><p>Audio is streamed continuously.</p><div><hr></div><h2>Step 3: Streaming ASR</h2><p>Instead of waiting for complete speech:</p><p>Traditional ASR:</p><pre><code><code>User speaks
     &#8595;
Speech ends
     &#8595;
ASR starts
</code></code></pre><p>High latency.</p><div><hr></div><p>Streaming ASR:</p><pre><code><code>Audio Chunk 1
Audio Chunk 2
Audio Chunk 3
</code></code></pre><p>ASR continuously emits partial transcripts.</p><p>Example:</p><pre><code><code>"Book"
"Book me"
"Book me a flight"
"Book me a flight to London"
</code></code></pre><p>This saves hundreds of milliseconds.</p><div><hr></div><h2>Step 4: Conversation Orchestrator</h2><p>Receives partial transcript.</p><p>Maintains conversation state.</p><p>Fetches:</p><ul><li><p>User profile</p></li><li><p>Conversation memory</p></li><li><p>Previous messages</p></li></ul><p>Builds prompt.</p><div><hr></div><h2>Step 5: LLM Inference Service</h2><p>Prompt sent to LLM.</p><p>Example:</p><pre><code><code>User:
Book me a flight to London

Context:
User prefers economy seats.
</code></code></pre><p>LLM begins generating tokens immediately.</p><p>Streaming output:</p><pre><code><code>Sure
Sure, I
Sure, I can
Sure, I can help
</code></code></pre><p>No need to wait for complete answer.</p><div><hr></div><h2>Step 6: TTS Service</h2><p>As soon as first tokens arrive:</p><pre><code><code>Sure,
</code></code></pre><p>TTS starts synthesis.</p><p>Produces audio stream immediately.</p><p>Pipeline:</p><pre><code><code>LLM Tokens
    &#8595;
TTS
    &#8595;
Audio Chunks
    &#8595;
User
</code></code></pre><p>This overlap is critical for achieving &lt;300 ms latency.</p><div><hr></div><h1>End-to-End Streaming Pipeline</h1><pre><code><code>User Speech
      &#8595;
Streaming ASR
      &#8595;
Partial Transcript
      &#8595;
LLM Streaming
      &#8595;
Partial Tokens
      &#8595;
Streaming TTS
      &#8595;
Audio Response
</code></code></pre><p>All stages run simultaneously.</p><div><hr></div><h1>Barge-In (Interruption Handling)</h1><h2>Problem</h2><p>AI is speaking:</p><pre><code><code>AI:
"Sure, I can help you book..."
</code></code></pre><p>User interrupts:</p><pre><code><code>"No, I meant Paris."
</code></code></pre><p>System must stop speaking immediately.</p><div><hr></div><h2>Barge-In Flow</h2><p>User audio detected.</p><p>Barge-In Service receives voice activity event.</p><pre><code><code>User Voice Detected
       &#8595;
Stop Current TTS
       &#8595;
Cancel Current LLM Generation
       &#8595;
Start New ASR Stream
</code></code></pre><div><hr></div><p>Conversation becomes:</p><pre><code><code>AI:
Sure I can help...

User:
No, I meant Paris.

AI:
Understood. You want Paris.
</code></code></pre><div><hr></div><h1>Session Management</h1><p>Session Service maintains:</p><ul><li><p>Session ID</p></li><li><p>User preferences</p></li><li><p>Current conversation state</p></li><li><p>Active model</p></li><li><p>Current TTS stream</p></li><li><p>Current ASR stream</p></li></ul><p>Hot session state stored in Redis.</p><pre><code><code>Session
      &#8595;
Redis
</code></code></pre><p>Access latency:</p><pre><code><code>&lt; 5 ms
</code></code></pre><p>Long-term history stored in distributed database.</p><div><hr></div><h1>Autoscaling Strategy</h1><h2>ASR Autoscaling</h2><p>Scale based on:</p><pre><code><code>Active Audio Streams
</code></code></pre><p>Metric:</p><pre><code><code>Streams per GPU
</code></code></pre><div><hr></div><h2>LLM Autoscaling</h2><p>Scale based on:</p><pre><code><code>Waiting Requests
Token Throughput
GPU Queue Length
</code></code></pre><div><hr></div><h2>TTS Autoscaling</h2><p>Scale based on:</p><pre><code><code>Concurrent Audio Synthesis Requests
</code></code></pre><div><hr></div><p>Kubernetes HPA scales services independently.</p><div><hr></div><h1>GPU Utilization Optimization</h1><p>Running one request per GPU wastes resources.</p><p>Bad:</p><pre><code><code>GPU
 &#9492;&#9472; Request A
</code></code></pre><p>Utilization:</p><pre><code><code>15%
</code></code></pre><div><hr></div><p>Use Continuous Batching.</p><p>Good:</p><pre><code><code>GPU
 &#9500;&#9472; Req A
 &#9500;&#9472; Req B
 &#9500;&#9472; Req C
 &#9500;&#9472; Req D
 &#9492;&#9472; Req E
</code></code></pre><p>Utilization:</p><pre><code><code>80-95%
</code></code></pre><div><hr></div><h1>GPU Scheduler</h1><p>Responsibilities:</p><ul><li><p>Assign requests to GPUs.</p></li><li><p>Perform dynamic batching.</p></li><li><p>Route to least loaded GPU.</p></li><li><p>Handle model placement.</p></li><li><p>Manage KV cache memory.</p></li></ul><div><hr></div><h1>Latency Breakdown (&lt;300 ms Target)</h1><div class="highlighted_code_block" data-attrs="{&quot;language&quot;:&quot;plaintext&quot;,&quot;nodeId&quot;:&quot;7670167e-1584-4281-9a91-5dc1f7c8bc56&quot;}" data-component-name="HighlightedCodeBlockToDOM"><pre class="shiki"><code class="language-plaintext">| Component       | Latency |
| --------------- | ------- |
| Network         | 20 ms   |
| Streaming ASR   | 50 ms   |
| Prompt Building | 10 ms   |
| LLM First Token | 80 ms   |
| Streaming TTS   | 80 ms   |
| Buffering       | 20 ms   |
</code></pre></div><p>Total:</p><pre><code><code>&#8776; 260 ms
</code></code></pre><div><hr></div><h1>High-Level Architecture</h1><pre><code><code>Client
   |
WebSocket Gateway
   |
Session Service
   |
Conversation Orchestrator
   |
   +----------------+
   |                |
Streaming ASR   Memory Service
   |                |
   +-------+--------+
           |
           v
      LLM Service
           |
           v
       TTS Service
           |
           v
      Audio Stream
           |
         Client
</code></code></pre><h3>Key Design Decisions</h3><ul><li><p>Streaming ASR instead of batch ASR.</p></li><li><p>Streaming token generation from LLM.</p></li><li><p>Streaming TTS synthesis.</p></li><li><p>Redis-backed session state.</p></li><li><p>Immediate barge-in cancellation.</p></li><li><p>Dynamic GPU batching.</p></li><li><p>Regional deployment with edge WebSocket gateways.</p></li><li><p>Stateless services with Kubernetes autoscaling.</p></li><li><p>Event-driven communication via Kafka/Pulsar.</p></li><li><p>Continuous GPU utilization monitoring and scheduling.</p></li></ul>]]></content:encoded></item><item><title><![CDATA[HLD: Design a Knowledge Base (KB) Cache for a RAG system serving 100M+ queries/day. Explain cache hierarchy (embedding, retrieval, LLM response), invalidation, freshness, semantic cache hits.]]></title><description><![CDATA[Functional Requirements (FR)]]></description><link>https://programmingappliedai.substack.com/p/hld-design-a-knowledge-base-kb-cache</link><guid isPermaLink="false">https://programmingappliedai.substack.com/p/hld-design-a-knowledge-base-kb-cache</guid><dc:creator><![CDATA[Shashank Mishra]]></dc:creator><pubDate>Thu, 23 Jul 2026 14:43:59 GMT</pubDate><enclosure url="iframe.php?url=https%3A%2F%2Fsubstackcdn.com%2Fimage%2Ffetch%2F%24s_%21riGX%21%2Cw_256%2Cc_limit%2Cf_auto%2Cq_auto%3Agood%2Cfl_progressive%3Asteep%2Fhttps%253A%252F%252Fsubstack-post-media.s3.amazonaws.com%252Fpublic%252Fimages%252F58e132e8-cd28-4037-b0ef-feabb2b68221_144x144.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2>Functional Requirements (FR)</h2><ul><li><p>Users should be able to submit natural language questions to the RAG system.</p></li><li><p>System should retrieve the most relevant documents/chunks from the knowledge base.</p></li><li><p>System should generate answers using retrieved context and an LLM.</p></li><li><p>System should cache query embeddings to avoid repeated embedding generation.</p></li><li><p>System should cache retrieval results to avoid repeated vector searches.</p></li><li><p>System should cache final LLM responses for repeated or semantically similar queries.</p></li><li><p>System should support semantic cache lookup based on embedding similarity.</p></li><li><p>System should allow ingestion, update, and deletion of knowledge base documents.</p></li><li><p>System should invalidate stale cache entries when underlying documents change.</p></li><li><p>System should provide source citations/metadata used for answer generation.</p></li><li><p>System should support multi-tenant isolation (different organizations/knowledge bases).</p></li><li><p>System should expose cache hit/miss metrics for monitoring and analytics.</p></li></ul><div><hr></div><h2>Non-Functional Requirements (NFR)</h2><ul><li><p>Support 100M+ queries per day.</p></li><li><p>Handle peak traffic of 10K&#8211;50K QPS.</p></li><li><p>Achieve P95 query latency below 500 ms for cached requests.</p></li><li><p>Achieve P99 latency below 2 seconds for uncached requests.</p></li><li><p>Maintain 99.99% service availability.</p></li><li><p>Scale horizontally without downtime.</p></li><li><p>Ensure fault tolerance with no single point of failure.</p></li><li><p>Support eventual consistency for distributed cache invalidation.</p></li><li><p>Minimize LLM and vector search costs through high cache hit ratios.</p></li><li><p>Maintain cache freshness after KB updates.</p></li><li><p>Support multi-region deployments with local cache access.</p></li><li><p>Ensure tenant-level security and data isolation.</p></li><li><p>Enable observability through metrics, logs, and distributed tracing.</p></li><li><p>Support rolling deployments and zero-downtime upgrades.</p></li><li><p>Provide disaster recovery and backup mechanisms.</p></li></ul><div><hr></div><h2>Core APIs</h2><h3>Query API</h3><pre><code><code>POST /v1/query
</code></code></pre><p>Request</p><pre><code><code>{
  "query": "What is GPT-5?",
  "tenantId": "org123",
  "userId": "user456"
}
</code></code></pre><p>Response</p><pre><code><code>{
  "answer": "GPT-5 is...",
  "sources": ["doc1", "doc2"],
  "cacheHit": "response_cache",
  "latencyMs": 45
}
</code></code></pre><div><hr></div><h3>Document Ingestion API</h3><pre><code><code>POST /v1/documents
</code></code></pre><p>Request</p><pre><code><code>{
  "documentId": "doc123",
  "content": "document content",
  "metadata": {
    "category": "AI"
  }
}
</code></code></pre><p>Response</p><pre><code><code>{
  "status": "success"
}
</code></code></pre><div><hr></div><h3>Document Update API</h3><pre><code><code>PUT /v1/documents/{documentId}
</code></code></pre><p>Request</p><pre><code><code>{
  "content": "updated content",
  "version": 5
}
</code></code></pre><p>Response</p><pre><code><code>{
  "status": "updated"
}
</code></code></pre><div><hr></div><h3>Cache Invalidation API</h3><pre><code><code>POST /v1/cache/invalidate
</code></code></pre><p>Request</p><pre><code><code>{
  "documentId": "doc123"
}
</code></code></pre><p>Response</p><pre><code><code>{
  "status": "invalidated"
}
</code></code></pre><div><hr></div><h2>Database Schema</h2><h3>Documents</h3><pre><code><code>CREATE TABLE documents (
    document_id VARCHAR(64) PRIMARY KEY,
    content TEXT,
    version BIGINT,
    metadata JSONB,
    updated_at TIMESTAMP
);
</code></code></pre><h3>Embeddings</h3><pre><code><code>CREATE TABLE embeddings (
    embedding_id BIGSERIAL PRIMARY KEY,
    document_id VARCHAR(64),
    embedding VECTOR(1536),
    version BIGINT
);
</code></code></pre><h3>Response Cache Metadata</h3><pre><code><code>CREATE TABLE response_cache (
    cache_key VARCHAR(255) PRIMARY KEY,
    answer TEXT,
    kb_version BIGINT,
    created_at TIMESTAMP,
    expires_at TIMESTAMP
);
</code></code></pre><h3>Retrieval Cache Metadata</h3><pre><code><code>CREATE TABLE retrieval_cache (
    query_hash VARCHAR(255) PRIMARY KEY,
    document_ids JSONB,
    kb_version BIGINT,
    created_at TIMESTAMP
);
</code></code></pre><div><hr></div><h2>Microservices</h2><ul><li><p>API Gateway</p></li><li><p>Query Orchestrator Service</p></li><li><p>Embedding Service</p></li><li><p>Embedding Cache Service</p></li><li><p>Retrieval Cache Service</p></li><li><p>Vector Search Service</p></li><li><p>Response Cache Service</p></li><li><p>LLM Service</p></li><li><p>Knowledge Base Service</p></li><li><p>Cache Invalidation Service</p></li><li><p>Metadata Service</p></li><li><p>Monitoring &amp; Analytics Service</p></li><li><p>Kafka/Pulsar Event Bus</p></li></ul><div><hr></div><h2>High-Level Request Flow</h2><pre><code><code>Client
   |
API Gateway
   |
Query Orchestrator
   |
   +--&gt; Response Cache
   |        |
   |        +--&gt; Hit --&gt; Return Answer
   |
   +--&gt; Embedding Cache
   |        |
   |        +--&gt; Miss --&gt; Embedding Service
   |
   +--&gt; Retrieval Cache
   |        |
   |        +--&gt; Miss --&gt; Vector Search
   |
   +--&gt; LLM Service
   |
Return Answer
</code></code></pre><h2>Microservices Interaction (Request Flow)</h2><h3>1. Client &#8594; API Gateway</h3><ul><li><p>User sends a query such as <em>&#8220;What is GPT-5?&#8221;</em></p></li><li><p>API Gateway performs authentication, rate limiting, request validation, and routing.</p></li><li><p>Request is forwarded to the Query Orchestrator Service.</p></li></ul><div><hr></div><h3>2. Query Orchestrator &#8594; Response Cache Service</h3><ul><li><p>Query Orchestrator first checks whether the final answer is already available in the Response Cache.</p></li><li><p>Cache lookup can happen in two ways:</p><ul><li><p>Exact match lookup using query hash.</p></li><li><p>Semantic lookup using query embedding similarity.</p></li></ul></li><li><p>If a valid cache entry exists, the response is returned immediately.</p></li><li><p>This is the fastest path and avoids all downstream processing.</p></li></ul><p><strong>Example</strong></p><pre><code><code>"What is GPT-5?"
</code></code></pre><p>already exists in cache.</p><p>Response is returned in ~10-50 ms.</p><div><hr></div><h3>3. Query Orchestrator &#8594; Embedding Cache Service</h3><p>If response cache misses:</p><ul><li><p>System needs query embedding.</p></li><li><p>Query Orchestrator checks Embedding Cache.</p></li></ul><p><strong>Cache Hit</strong></p><ul><li><p>Cached embedding vector is returned.</p></li></ul><p><strong>Cache Miss</strong></p><ul><li><p>Request goes to Embedding Service.</p></li><li><p>Embedding model generates vector.</p></li><li><p>Generated vector is stored in Embedding Cache for future use.</p></li></ul><p>Example:</p><pre><code><code>"What is GPT-5?"
</code></code></pre><p>&#8595;</p><pre><code><code>[0.12, 0.45, 0.98 ...]
</code></code></pre><div><hr></div><h3>4. Query Orchestrator &#8594; Retrieval Cache Service</h3><p>Once query embedding is available:</p><ul><li><p>System checks Retrieval Cache.</p></li><li><p>Retrieval Cache stores previously retrieved document IDs for similar queries.</p></li></ul><p><strong>Cache Hit</strong></p><pre><code><code>Query Embedding
       &#8595;
[Doc1, Doc7, Doc9]
</code></code></pre><p>Documents are returned directly.</p><p><strong>Cache Miss</strong></p><p>System performs vector search.</p><div><hr></div><h3>5. Query Orchestrator &#8594; Vector Search Service</h3><ul><li><p>Vector Search Service receives query embedding.</p></li><li><p>Searches Vector Database using Approximate Nearest Neighbor (ANN) algorithms such as HNSW or IVF.</p></li><li><p>Retrieves Top-K relevant chunks/documents.</p></li></ul><p>Example:</p><pre><code><code>Query:
"What is GPT-5?"
</code></code></pre><p>Retrieved:</p><pre><code><code>Doc12
Doc19
Doc42
</code></code></pre><p>Results are stored in Retrieval Cache.</p><div><hr></div><h3>6. Query Orchestrator &#8594; Knowledge Base Service</h3><ul><li><p>Query Orchestrator requests full content for retrieved document IDs.</p></li><li><p>KB Service fetches chunk text and metadata.</p></li></ul><p>Example:</p><pre><code><code>Doc12 &#8594; GPT-5 architecture
Doc19 &#8594; GPT-5 capabilities
Doc42 &#8594; GPT-5 release information
</code></code></pre><p>These chunks form the context.</p><div><hr></div><h3>7. Query Orchestrator &#8594; LLM Service</h3><ul><li><p>Query and retrieved context are sent to the LLM Service.</p></li><li><p>LLM Service constructs prompt.</p></li></ul><p>Example:</p><pre><code><code>System Prompt

Retrieved Context:
[Doc12]
[Doc19]
[Doc42]

User Query:
What is GPT-5?
</code></code></pre><ul><li><p>LLM generates final answer.</p></li></ul><div><hr></div><h3>8. Query Orchestrator &#8594; Response Cache Service</h3><p>Before returning answer:</p><ul><li><p>Generated response is stored in Response Cache.</p></li><li><p>Metadata is stored:</p><ul><li><p>Query hash</p></li><li><p>Embedding hash</p></li><li><p>Retrieved document IDs</p></li><li><p>KB version</p></li><li><p>TTL</p></li></ul></li></ul><p>This allows future requests to avoid LLM generation.</p><div><hr></div><h3>9. Query Orchestrator &#8594; Client</h3><p>Final response is returned.</p><pre><code><code>{
  "answer": "GPT-5 is...",
  "sources": ["Doc12", "Doc19", "Doc42"],
  "cacheHit": false
}
</code></code></pre><div><hr></div><h1>Document Update Flow</h1><p>When knowledge base content changes:</p><h3>1. Admin &#8594; KB Service</h3><p>Document update request arrives.</p><pre><code><code>Doc19 Updated
</code></code></pre><div><hr></div><h3>2. KB Service &#8594; Vector Search Service</h3><ul><li><p>New document embedding is generated.</p></li><li><p>Old vector is replaced in Vector DB.</p></li></ul><div><hr></div><h3>3. KB Service &#8594; Kafka/Event Bus</h3><p>Publish event:</p><pre><code><code>DocumentUpdated
{
   docId: 19,
   version: 22
}
</code></code></pre><div><hr></div><h3>4. Event Bus &#8594; Cache Invalidation Service</h3><p>Cache Invalidation Service consumes update event.</p><div><hr></div><h3>5. Cache Invalidation Service &#8594; Retrieval Cache</h3><p>Invalidate retrieval entries containing Doc19.</p><pre><code><code>QueryA &#8594; [Doc19, Doc22]
QueryB &#8594; [Doc7, Doc19]
</code></code></pre><p>Both entries removed.</p><div><hr></div><h3>6. Cache Invalidation Service &#8594; Response Cache</h3><p>Invalidate responses generated using Doc19.</p><pre><code><code>ResponseX
ResponseY
ResponseZ
</code></code></pre><p>All removed.</p><div><hr></div><h3>7. Fresh Requests Use New Data</h3><p>Future queries:</p><pre><code><code>Query
  &#8595;
Vector Search
  &#8595;
Updated Doc19
  &#8595;
LLM
</code></code></pre><p>Users receive fresh answers.</p><div><hr></div><h1>End-to-End Summary</h1><pre><code><code>User Query
    &#8595;
API Gateway
    &#8595;
Query Orchestrator
    &#8595;
Response Cache ?
    &#8595; miss
Embedding Cache ?
    &#8595; miss
Embedding Service
    &#8595;
Retrieval Cache ?
    &#8595; miss
Vector Search
    &#8595;
Knowledge Base
    &#8595;
LLM Service
    &#8595;
Response Cache Update
    &#8595;
User
</code></code></pre><p>The <strong>Query Orchestrator Service</strong> is the central coordinator. All other services (cache, embedding, vector search, KB, LLM) are specialized services that it calls in sequence to answer the query efficiently.</p>]]></content:encoded></item><item><title><![CDATA[HLD: Design Device backup and scheduler]]></title><description><![CDATA[Let's design]]></description><link>https://programmingappliedai.substack.com/p/hld-design-device-backup-and-scheduler</link><guid isPermaLink="false">https://programmingappliedai.substack.com/p/hld-design-device-backup-and-scheduler</guid><dc:creator><![CDATA[Shashank Mishra]]></dc:creator><pubDate>Wed, 08 Jul 2026 17:44:08 GMT</pubDate><enclosure url="iframe.php?url=https%3A%2F%2Fsubstackcdn.com%2Fimage%2Ffetch%2F%24s_%21riGX%21%2Cw_256%2Cc_limit%2Cf_auto%2Cq_auto%3Agood%2Cfl_progressive%3Asteep%2Fhttps%253A%252F%252Fsubstack-post-media.s3.amazonaws.com%252Fpublic%252Fimages%252F58e132e8-cd28-4037-b0ef-feabb2b68221_144x144.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p><strong>FR:</strong></p><ol><li><p>Schedule device backups.</p></li><li><p>Trigger automatic backups as per schedule.</p></li><li><p>View backup status and history.</p></li><li><p>Restore device data from selected backup.</p></li><li><p>Send backup/restore success or failure notifications.</p></li></ol><p><strong>NFR:</strong></p><ol><li><p>High availability of backup and restore services.</p></li><li><p>Secure data storage and transmission through encryption.</p></li><li><p>Scalable to support multiple devices concurrently.</p></li><li><p>Minimal impact on device performance during backup.</p></li><li><p>Maintain backup data integrity and reliability.</p></li></ol><p><strong>API&#8217;s with Request and Response</strong></p><h3>1. Create Backup Schedule</h3><p><strong>API:</strong> <code>POST /api/v1/backup/schedules</code></p><p><strong>Request</strong></p><pre><code><code>{
  "deviceId": "DEV001",
  "frequency": "DAILY",
  "time": "02:00"
}
</code></code></pre><p><strong>Response</strong></p><pre><code><code>{
  "scheduleId": "SCH001",
  "status": "CREATED",
  "message": "Backup schedule created successfully"
}
</code></code></pre><div><hr></div><h3>2. Trigger Backup</h3><p><strong>API:</strong> <code>POST /api/v1/backups</code></p><p><strong>Request</strong></p><pre><code><code>{
  "deviceId": "DEV001",
  "backupType": "FULL"
}
</code></code></pre><p><strong>Response</strong></p><pre><code><code>{
  "backupId": "BKP001",
  "status": "IN_PROGRESS",
  "message": "Backup initiated successfully"
}
</code></code></pre><div><hr></div><h3>3. Get Backup Status</h3><p><strong>API:</strong> <code>GET /api/v1/backups/{backupId}</code></p><p><strong>Request</strong></p><pre><code><code>{
  "backupId": "BKP001"
}
</code></code></pre><p><strong>Response</strong></p><pre><code><code>{
  "backupId": "BKP001",
  "deviceId": "DEV001",
  "status": "COMPLETED",
  "backupTime": "2026-07-08T02:00:00Z"
}
</code></code></pre><div><hr></div><h3>4. Get Available Backups for Restore</h3><p><strong>API:</strong> <code>GET /api/v1/devices/{deviceId}/backups</code></p><p><strong>Request</strong></p><pre><code><code>{
  "deviceId": "DEV001"
}
</code></code></pre><p><strong>Response</strong></p><pre><code><code>{
  "backups": [
    {
      "backupId": "BKP001",
      "createdAt": "2026-07-08T02:00:00Z"
    },
    {
      "backupId": "BKP002",
      "createdAt": "2026-07-07T02:00:00Z"
    }
  ]
}
</code></code></pre><div><hr></div><h3>5. Restore Backup</h3><p><strong>API:</strong> <code>POST /api/v1/restores</code></p><p><strong>Request</strong></p><pre><code><code>{
  "deviceId": "DEV001",
  "backupId": "BKP001"
}
</code></code></pre><p><strong>Response</strong></p><pre><code><code>{
  "restoreId": "RST001",
  "status": "IN_PROGRESS",
  "message": "Restore initiated successfully"
}
</code></code></pre><div><hr></div><h3>6. Get Restore Status</h3><p><strong>API:</strong> <code>GET /api/v1/restores/{restoreId}</code></p><p><strong>Request</strong></p><pre><code><code>{
  "restoreId": "RST001"
}
</code></code></pre><p><strong>Response</strong></p><pre><code><code>{
  "restoreId": "RST001",
  "deviceId": "DEV001",
  "status": "COMPLETED",
  "restoredAt": "2026-07-08T05:00:00Z"
}</code></code></pre><p><strong>Databases and Schema</strong></p><p><strong>Database Choice</strong></p><ul><li><p>PostgreSQL &#8211; Backup schedules, backup metadata, restore jobs, notifications, audit logs</p></li><li><p>Redis &#8211; Caching and job scheduling</p></li><li><p>Object Storage (S3 compatible) &#8211; Backup file storage</p></li><li><p>Elasticsearch/OpenSearch (Optional) &#8211; Log search and analytics</p></li></ul><p><strong>Tables</strong></p><p><strong>Device</strong></p><ul><li><p>device_id (PK, UUID)</p></li><li><p>device_name (VARCHAR)</p></li><li><p>device_type (VARCHAR)</p></li><li><p>owner_id (VARCHAR)</p></li><li><p>status (VARCHAR)</p></li><li><p>created_at (TIMESTAMP)</p></li></ul><p><strong>Backup_Schedule</strong></p><ul><li><p>schedule_id (PK, UUID)</p></li><li><p>device_id (FK, UUID)</p></li><li><p>frequency (VARCHAR)</p></li><li><p>backup_time (TIME)</p></li><li><p>is_active (BOOLEAN)</p></li><li><p>created_at (TIMESTAMP)</p></li><li><p>updated_at (TIMESTAMP)</p></li></ul><p><strong>Backup_Job</strong></p><ul><li><p>backup_id (PK, UUID)</p></li><li><p>device_id (FK, UUID)</p></li><li><p>schedule_id (FK, UUID)</p></li><li><p>backup_type (VARCHAR)</p></li><li><p>status (VARCHAR)</p></li><li><p>file_size (BIGINT)</p></li><li><p>storage_path (VARCHAR)</p></li><li><p>started_at (TIMESTAMP)</p></li><li><p>completed_at (TIMESTAMP)</p></li></ul><p><strong>Backup_Version</strong></p><ul><li><p>version_id (PK, UUID)</p></li><li><p>backup_id (FK, UUID)</p></li><li><p>version_number (INT)</p></li><li><p>checksum (VARCHAR)</p></li><li><p>retention_days (INT)</p></li><li><p>created_at (TIMESTAMP)</p></li></ul><p><strong>Restore_Job</strong></p><ul><li><p>restore_id (PK, UUID)</p></li><li><p>device_id (FK, UUID)</p></li><li><p>backup_id (FK, UUID)</p></li><li><p>status (VARCHAR)</p></li><li><p>initiated_by (VARCHAR)</p></li><li><p>started_at (TIMESTAMP)</p></li><li><p>completed_at (TIMESTAMP)</p></li></ul><p><strong>Notification</strong></p><ul><li><p>notification_id (PK, UUID)</p></li><li><p>device_id (FK, UUID)</p></li><li><p>event_type (VARCHAR)</p></li><li><p>recipient (VARCHAR)</p></li><li><p>status (VARCHAR)</p></li><li><p>sent_at (TIMESTAMP)</p></li></ul><p><strong>Audit_Log</strong></p><ul><li><p>audit_id (PK, UUID)</p></li><li><p>entity_type (VARCHAR)</p></li><li><p>entity_id (UUID)</p></li><li><p>action (VARCHAR)</p></li><li><p>performed_by (VARCHAR)</p></li><li><p>timestamp (TIMESTAMP)</p></li><li><p>remarks (TEXT)</p></li></ul><p><strong>Relationships</strong></p><ul><li><p>Device &#8594; Backup_Schedule (1:N)</p></li><li><p>Device &#8594; Backup_Job (1:N)</p></li><li><p>Backup_Job &#8594; Backup_Version (1:N)</p></li><li><p>Device &#8594; Restore_Job (1:N)</p></li><li><p>Backup_Job &#8594; Restore_Job (1:N)</p></li><li><p>Device &#8594; Notification (1:N)</p></li><li><p>All entities &#8594; Audit_Log (1:N)</p></li></ul><p><strong>Microservices Architecture &#8211; Device Backup Scheduler &amp; Restore</strong></p><ol><li><p><strong>API Gateway</strong></p><ul><li><p>Single entry point for all client requests</p></li><li><p>Authentication, authorization, routing, rate limiting</p></li></ul></li><li><p><strong>Device Management Service</strong></p><ul><li><p>Manages device registration and device metadata</p></li><li><p>Provides device details to backup and restore services</p></li></ul></li><li><p><strong>Backup Scheduler Service</strong></p><ul><li><p>Creates and manages backup schedules</p></li><li><p>Triggers backup jobs based on configured frequency</p></li></ul></li><li><p><strong>Backup Service</strong></p><ul><li><p>Executes backup operations</p></li><li><p>Stores backup metadata and uploads backup files to object storage</p></li></ul></li><li><p><strong>Restore Service</strong></p><ul><li><p>Retrieves backup data</p></li><li><p>Initiates and monitors restore operations</p></li></ul></li><li><p><strong>Notification Service</strong></p><ul><li><p>Sends email/SMS/in-app notifications for backup and restore events</p></li></ul></li><li><p><strong>Audit &amp; Logging Service</strong></p><ul><li><p>Records user actions and system events</p></li><li><p>Provides audit trail for compliance and troubleshooting</p></li></ul></li><li><p><strong>Storage Service</strong></p><ul><li><p>Manages backup file storage and retrieval from object storage</p></li></ul></li><li><p><strong>Auth Service</strong></p><ul><li><p>User authentication and authorization</p></li><li><p>Issues and validates JWT/OAuth tokens</p></li></ul></li></ol><div><hr></div><p><strong>Service Interaction Flow</strong></p><p><strong>Backup Scheduling</strong></p><ol><li><p>Client &#8594; API Gateway</p></li><li><p>API Gateway &#8594; Auth Service (token validation)</p></li><li><p>API Gateway &#8594; Backup Scheduler Service</p></li><li><p>Backup Scheduler Service &#8594; Device Management Service (validate device)</p></li><li><p>Backup Scheduler Service &#8594; PostgreSQL (save schedule)</p></li></ol><p><strong>Backup Execution</strong></p><ol><li><p>Scheduler triggers Backup Service</p></li><li><p>Backup Service &#8594; Device Management Service (device details)</p></li><li><p>Backup Service &#8594; Storage Service (store backup file)</p></li><li><p>Backup Service &#8594; PostgreSQL (save metadata)</p></li><li><p>Backup Service &#8594; Notification Service (backup status)</p></li><li><p>Notification Service &#8594; User</p></li></ol><p><strong>Restore Execution</strong></p><ol><li><p>Client &#8594; API Gateway</p></li><li><p>API Gateway &#8594; Restore Service</p></li><li><p>Restore Service &#8594; Backup Service (backup metadata)</p></li><li><p>Restore Service &#8594; Storage Service (retrieve backup file)</p></li><li><p>Restore Service &#8594; Device Management Service (device validation)</p></li><li><p>Restore Service &#8594; PostgreSQL (update restore status)</p></li><li><p>Restore Service &#8594; Notification Service (restore status)</p></li></ol><p><strong>Audit Flow</strong></p><ol><li><p>Every service publishes events</p></li><li><p>Audit &amp; Logging Service consumes events</p></li><li><p>Audit records stored in Audit_Log table</p></li></ol><p><strong>Communication Pattern</strong></p><ul><li><p>Synchronous: REST APIs (API Gateway &#8596; Services)</p></li><li><p>Asynchronous: Kafka/RabbitMQ events for Backup Trigger, Restore Trigger, Notifications, Audit Logging</p></li><li><p>Database per service pattern</p></li><li><p>Object Storage for backup files</p></li><li><p>Redis for caching and scheduled job execution</p></li></ul><p><strong>High-Level Flow</strong><br>Client &#8594; API Gateway &#8594; Auth Service &#8594; Backup Scheduler Service &#8594; Backup Service &#8594; Storage Service &#8594; Restore Service &#8594; Notification Service &#8594; Audit Service &#8594; Databases/Object Storage/Event Bus.</p><p></p><p></p>]]></content:encoded></item><item><title><![CDATA[HLD: Design Container Management System (Manage / Move / Deploy Containers Across Networks)]]></title><description><![CDATA[Think of this as a simplified version of Kubernetes + Cluster Federation, where containers can be deployed, migrated, monitored, and managed across multiple data centers, cloud providers, and networks]]></description><link>https://programmingappliedai.substack.com/p/hld-design-container-management-system</link><guid isPermaLink="false">https://programmingappliedai.substack.com/p/hld-design-container-management-system</guid><dc:creator><![CDATA[Shashank Mishra]]></dc:creator><pubDate>Mon, 08 Jun 2026 17:49:07 GMT</pubDate><enclosure url="iframe.php?url=https%3A%2F%2Fsubstackcdn.com%2Fimage%2Ffetch%2F%24s_%21riGX%21%2Cw_256%2Cc_limit%2Cf_auto%2Cq_auto%3Agood%2Cfl_progressive%3Asteep%2Fhttps%253A%252F%252Fsubstack-post-media.s3.amazonaws.com%252Fpublic%252Fimages%252F58e132e8-cd28-4037-b0ef-feabb2b68221_144x144.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h3>Functional Requirements</h3><ol><li><p>Deploy containers on available compute nodes using Docker/OCI compliant images.</p></li><li><p>Migrate running containers across nodes or clusters while preserving application state and network connectivity.</p></li><li><p>Manage container lifecycle operations including start, stop, restart, update, and scaling.</p></li><li><p>Create and manage virtual networks, service discovery, and cross-network communication between containers.</p></li><li><p>Continuously monitor container and node health, collect metrics, detect failures, and trigger automatic recovery actions.</p></li></ol><div><hr></div><h3>Non-Functional Requirements</h3><ol><li><p>Ensure high availability with a target uptime of at least 99.99%.</p></li><li><p>Scale to support up to 100,000 nodes and 1 million running containers.</p></li><li><p>Achieve container deployment and scheduling latency of less than 5 seconds.</p></li><li><p>Provide fault tolerance such that node, network, or service failures do not cause application downtime.</p></li><li><p>Enforce enterprise-grade security through RBAC, TLS-encrypted communication, image signing, verification, and audit logging.</p></li></ol><div><hr></div><h1>Core APIs</h1><div><hr></div><h2>Deploy Container</h2><pre><code></code></pre><pre><code><code>POST /v1/containers</code></code></pre><p>Request</p><pre><code></code></pre><pre><code><code>{
  "image":"nginx:latest",
  "cpu":"2",
  "memory":"4GB",
  "network_id":"net-123",
  "replicas":3
}</code></code></pre><p>Response</p><pre><code></code></pre><pre><code><code>{
  "container_id":"ctr-123",
  "status":"DEPLOYING"
}</code></code></pre><div><hr></div><h2>Get Container</h2><pre><code></code></pre><pre><code><code>GET /v1/containers/{containerId}</code></code></pre><p>Response</p><pre><code></code></pre><pre><code><code>{
  "container_id":"ctr-123",
  "status":"RUNNING",
  "node_id":"node-45",
  "ip":"10.0.1.20"
}</code></code></pre><div><hr></div><h2>Migrate Container</h2><pre><code></code></pre><pre><code><code>POST /v1/containers/{containerId}/migrate</code></code></pre><p>Request</p><pre><code></code></pre><pre><code><code>{
  "target_node":"node-99"
}</code></code></pre><p>Response</p><pre><code></code></pre><pre><code><code>{
  "migration_id":"mig-111",
  "status":"IN_PROGRESS"
}</code></code></pre><div><hr></div><h2>Scale Container</h2><pre><code></code></pre><pre><code><code>POST /v1/containers/{containerId}/scale</code></code></pre><p>Request</p><pre><code></code></pre><pre><code><code>{
  "replicas":20
}</code></code></pre><p>Response</p><pre><code></code></pre><pre><code><code>{
  "status":"SCALING"
}</code></code></pre><div><hr></div><h2>Create Network</h2><pre><code></code></pre><pre><code><code>POST /v1/networks</code></code></pre><p>Request</p><pre><code></code></pre><pre><code><code>{
  "name":"payment-network",
  "cidr":"10.10.0.0/16"
}</code></code></pre><p>Response</p><pre><code></code></pre><pre><code><code>{
  "network_id":"net-123"
}</code></code></pre><div><hr></div><h1>Database Choice</h1><div class="highlighted_code_block" data-attrs="{&quot;language&quot;:&quot;plaintext&quot;,&quot;nodeId&quot;:&quot;7956f0d5-f05c-4a3e-a5b9-c7a8e42b027e&quot;}" data-component-name="HighlightedCodeBlockToDOM"><pre class="shiki"><code class="language-plaintext">| Component          | DB            |
| ------------------ | ------------- |
| Container Metadata | PostgreSQL    |
| Cluster State      | etcd          |
| Metrics            | Cassandra     |
| Logs               | Elasticsearch |
| Cache              | Redis         |
</code></pre></div><div><hr></div><h1>Database Schemas</h1><h2>Container</h2><pre><code></code></pre><pre><code><code>{
  "container_id":"ctr-123",
  "image":"nginx:latest",
  "status":"RUNNING",
  "node_id":"node-45",
  "network_id":"net-123",
  "cpu":"2",
  "memory":"4GB",
  "created_at":"timestamp"
}</code></code></pre><div><hr></div><h2>Node</h2><pre><code></code></pre><pre><code><code>{
  "node_id":"node-45",
  "hostname":"worker-1",
  "ip":"192.168.1.10",
  "cpu_total":"64",
  "cpu_available":"20",
  "memory_total":"256GB",
  "memory_available":"120GB",
  "status":"HEALTHY"
}</code></code></pre><div><hr></div><h2>Cluster</h2><pre><code></code></pre><pre><code><code>{
  "cluster_id":"cluster-1",
  "name":"us-east-cluster",
  "region":"us-east",
  "status":"ACTIVE"
}</code></code></pre><div><hr></div><h2>Network</h2><pre><code></code></pre><pre><code><code>{
  "network_id":"net-123",
  "name":"payment-network",
  "cidr":"10.10.0.0/16",
  "gateway":"10.10.0.1"
}</code></code></pre><div><hr></div><h2>Migration Job</h2><pre><code></code></pre><pre><code><code>{
  "migration_id":"mig-111",
  "container_id":"ctr-123",
  "source_node":"node-45",
  "target_node":"node-99",
  "status":"IN_PROGRESS",
  "created_at":"timestamp"
}</code></code></pre><div><hr></div><h1>High Level Components</h1><pre><code></code></pre><pre><code><code>                    +------------------+
                    |      User        |
                    +---------+--------+
                              |
                              v
                    +------------------+
                    |    API Gateway   |
                    +---------+--------+
                              |
          -----------------------------------------
          |              |            |           |
          v              v            v           v

+----------------+ +--------------+ +---------------+
| Deployment     | | Migration    | | Network       |
| Service        | | Service      | | Service       |
+-------+--------+ +------+-------+ +-------+-------+
        |                 |                 |
        |                 |                 |
        v                 v                 v

+--------------------------------------------------+
|              Scheduler Service                   |
+--------------------------------------------------+
                        |
                        v

+--------------------------------------------------+
|              Cluster Manager                     |
+--------------------------------------------------+
                        |
        -----------------------------------
        |                |               |
        v                v               v

+------------+ +-------------+ +-------------+
| Node Agent | | Node Agent  | | Node Agent  |
| Node-1     | | Node-2      | | Node-N      |
+------------+ +-------------+ +-------------+</code></code></pre><div><hr></div><h1>Container Deployment Flow</h1><pre><code></code></pre><pre><code><code>User
 |
 | Deploy Container
 v

API Gateway
 |
 v

Deployment Service
 |
 v

Scheduler
 |
 | Find best node
 v

Cluster Manager
 |
 v

Node Agent
 |
 | Pull Image
 | Create Container
 v

Container Runtime
 |
 v

Container Running</code></code></pre><div><hr></div><h1>Container Migration Flow</h1><pre><code></code></pre><pre><code><code>User
 |
 | Migrate Container
 v

Migration Service
 |
 v

Scheduler
 |
 | Select Target Node
 v

Checkpoint Service
 |
 | Save Container State
 v

Target Node Agent
 |
 | Restore State
 v

Network Service
 |
 | Update Routing
 v

Container Running on New Node</code></code></pre><div><hr></div><h1>Microservices</h1><h3>1. API Gateway</h3><ul><li><p>Authentication<br></p></li><li><p>Rate limiting<br></p></li><li><p>Routing<br></p></li></ul><h3>2. Deployment Service</h3><ul><li><p>Container deployment<br></p></li><li><p>Scaling requests<br></p></li></ul><h3>3. Scheduler Service</h3><ul><li><p>Node selection<br></p></li><li><p>Resource allocation<br></p></li></ul><h3>4. Migration Service</h3><ul><li><p>Container relocation<br></p></li><li><p>State transfer<br></p></li></ul><h3>5. Network Service</h3><ul><li><p>Overlay networking<br></p></li><li><p>Service discovery<br></p></li></ul><h3>6. Cluster Manager</h3><ul><li><p>Cluster state management<br></p></li><li><p>Node registration<br></p></li></ul><h3>7. Health Monitoring Service</h3><ul><li><p>Metrics collection<br></p></li><li><p>Alerting<br></p></li></ul><h3>8. Auto-Healing Service</h3><ul><li><p>Restart failed containers<br></p></li><li><p>Reschedule workloads<br></p></li></ul><h3>9. Image Registry Service</h3><ul><li><p>Image storage<br></p></li><li><p>Image versioning<br></p></li></ul><h3>10. Audit &amp; Security Service</h3><ul><li><p>RBAC<br></p></li><li><p>Secrets management<br></p></li><li><p>Compliance logs<br></p></li></ul><div><hr></div><h1>Microservice Interaction</h1><pre><code></code></pre><pre><code><code>                 +----------------+
                 | API Gateway    |
                 +-------+--------+
                         |
     ------------------------------------------------
     |              |              |                |
     v              v              v                v

Deployment   Migration      Network         Monitoring
 Service      Service       Service           Service
     |              |             |                |
     ------------------------------------------------
                         |
                         v

                  Scheduler
                         |
                         v

                 Cluster Manager
                         |
         ---------------------------------
         |               |               |
         v               v               v

      Node Agent     Node Agent      Node Agent
         |               |               |
         ---------------------------------
                         |
                         v

                Container Runtime
             (containerd / Docker)</code></code></pre><div><hr></div><h1>Bottlenecks &amp; Scaling</h1><h3>Scheduler Bottleneck</h3><ul><li><p>Use sharded schedulers.<br></p></li><li><p>Leader election via etcd.<br></p></li></ul><h3>Metrics Explosion</h3><ul><li><p>Store metrics in Cassandra.<br></p></li><li><p>Aggregate before persistence.<br></p></li></ul><h3>Container Migration</h3><ul><li><p>Use incremental checkpoints.<br></p></li><li><p>Transfer only changed memory pages.<br></p></li></ul><h3>Multi-Region Networking</h3><ul><li><p>Overlay network (VXLAN/WireGuard).<br></p></li><li><p>Global service discovery.<br></p></li></ul><h3>Cluster State</h3><ul><li><p>Store in etcd with Raft consensus.<br></p></li><li><p>Multiple replicas for HA.<br></p></li></ul><p>This design is very close to how modern orchestration platforms such as Kubernetes, Nomad, and Docker Swarm manage large-scale container deployments across clusters and networks.</p>]]></content:encoded></item><item><title><![CDATA[HLD: TrackGen -Design a tracking if (TrackGen) product]]></title><description><![CDATA[If you&#8217;re looking for paid 1:1 mentorship with a strong focus on LLD (core emphasis on Multithreading), HLD, DSA, and system design research papers, feel free to reach out.]]></description><link>https://programmingappliedai.substack.com/p/hld-trackgen-design-a-tracking-if</link><guid isPermaLink="false">https://programmingappliedai.substack.com/p/hld-trackgen-design-a-tracking-if</guid><dc:creator><![CDATA[Shashank Mishra]]></dc:creator><pubDate>Mon, 08 Jun 2026 17:22:28 GMT</pubDate><enclosure url="iframe.php?url=https%3A%2F%2Fsubstackcdn.com%2Fimage%2Ffetch%2F%24s_%21riGX%21%2Cw_256%2Cc_limit%2Cf_auto%2Cq_auto%3Agood%2Cfl_progressive%3Asteep%2Fhttps%253A%252F%252Fsubstack-post-media.s3.amazonaws.com%252Fpublic%252Fimages%252F58e132e8-cd28-4037-b0ef-feabb2b68221_144x144.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h3><strong>If you&#8217;re looking for paid 1:1 mentorship with a strong focus on LLD (core emphasis on Multithreading), HLD, DSA, and system design research papers, feel free to reach out.</strong></h3><p>&#128233; <strong>Contact:</strong> programmingappliedai@gmail.com</p><h2>Functional Requirements (FR)</h2><h3>1. Asset Tracking</h3><ul><li><p>System should track assets (packages, vehicles, devices, orders) in real-time.</p></li><li><p>Support GPS coordinate updates.</p></li></ul><h3>2. Location History</h3><ul><li><p>Store and retrieve complete location history of tracked entities.</p></li><li><p>Allow querying historical movement.</p></li></ul><h3>3. Geofence Management</h3><ul><li><p>Create geofences around specific locations.</p></li><li><p>Trigger events when tracked entities enter or exit geofences.</p></li></ul><h3>4. Alerts &amp; Notifications</h3><ul><li><p>Generate alerts for:</p><ul><li><p>Geofence breach</p></li><li><p>Device offline</p></li><li><p>Route deviation</p></li><li><p>Low battery</p></li></ul></li></ul><h3>5. Tracking Dashboard</h3><ul><li><p>Display current location, status, speed, route, and historical trails.</p></li><li><p>Support filtering and search.</p></li></ul><div><hr></div><h1>Non-Functional Requirements (NFR)</h1><h3>1. High Availability</h3><ul><li><p>99.99% uptime.</p></li></ul><h3>2. Scalability</h3><ul><li><p>Support 10M+ tracked devices.</p></li><li><p>Support 100K location updates/sec.</p></li></ul><h3>3. Low Latency</h3><ul><li><p>Location updates visible within 2-3 seconds.</p></li></ul><h3>4. Durability</h3><ul><li><p>No loss of tracking events.</p></li></ul><h3>5. Security</h3><ul><li><p>OAuth/JWT authentication.</p></li><li><p>Encrypted data in transit and at rest.</p></li></ul><div><hr></div><h1>APIs</h1><div><hr></div><h2>1. Register Tracking Device</h2><h3>Request</h3><pre><code></code></pre><pre><code><code>POST /api/v1/devices</code></code></pre><pre><code></code></pre><pre><code><code>{
  "deviceId": "DEV123",
  "assetType": "VEHICLE",
  "assetId": "CAR123"
}</code></code></pre><h3>Response</h3><pre><code></code></pre><pre><code><code>{
  "deviceId": "DEV123",
  "status": "REGISTERED"
}</code></code></pre><div><hr></div><h2>2. Update Location</h2><h3>Request</h3><pre><code></code></pre><pre><code><code>POST /api/v1/location/update</code></code></pre><pre><code></code></pre><pre><code><code>{
  "deviceId": "DEV123",
  "latitude": 12.9716,
  "longitude": 77.5946,
  "speed": 45,
  "timestamp": 1745000000
}</code></code></pre><h3>Response</h3><pre><code></code></pre><pre><code><code>{
  "status": "SUCCESS"
}</code></code></pre><div><hr></div><h2>3. Get Current Location</h2><h3>Request</h3><pre><code></code></pre><pre><code><code>GET /api/v1/location/current/{deviceId}</code></code></pre><h3>Response</h3><pre><code></code></pre><pre><code><code>{
  "deviceId": "DEV123",
  "latitude": 12.9716,
  "longitude": 77.5946,
  "speed": 45,
  "timestamp": 1745000000
}</code></code></pre><div><hr></div><h2>4. Get Location History</h2><h3>Request</h3><pre><code></code></pre><pre><code><code>GET /api/v1/location/history</code></code></pre><pre><code></code></pre><pre><code><code>{
  "deviceId": "DEV123",
  "startTime": 1745000000,
  "endTime": 1746000000
}</code></code></pre><h3>Response</h3><pre><code></code></pre><pre><code><code>{
  "locations": [
    {
      "latitude": 12.9716,
      "longitude": 77.5946,
      "timestamp": 1745000000
    }
  ]
}</code></code></pre><div><hr></div><h2>5. Create Geofence</h2><h3>Request</h3><pre><code></code></pre><pre><code><code>POST /api/v1/geofence</code></code></pre><pre><code></code></pre><pre><code><code>{
  "geofenceId": "GF123",
  "name": "Warehouse",
  "centerLatitude": 12.9716,
  "centerLongitude": 77.5946,
  "radiusMeters": 500
}</code></code></pre><h3>Response</h3><pre><code></code></pre><pre><code><code>{
  "status": "CREATED"
}</code></code></pre><div><hr></div><h2>6. Get Alerts</h2><h3>Request</h3><pre><code></code></pre><pre><code><code>GET /api/v1/alerts/{deviceId}</code></code></pre><h3>Response</h3><pre><code></code></pre><pre><code><code>{
  "alerts": [
    {
      "alertType": "GEOFENCE_EXIT",
      "timestamp": 1745000000
    }
  ]
}</code></code></pre><div><hr></div><h1>Database Design</h1><h2>Device Table</h2><pre><code></code></pre><pre><code><code>{
  "deviceId": "DEV123",
  "assetId": "CAR123",
  "assetType": "VEHICLE",
  "status": "ACTIVE",
  "registeredAt": "2026-01-01T10:00:00Z"
}</code></code></pre><p>Partition Key:</p><pre><code></code></pre><pre><code><code>deviceId</code></code></pre><p>Database:</p><pre><code></code></pre><pre><code><code>PostgreSQL</code></code></pre><div><hr></div><h2>Current Location Table</h2><pre><code></code></pre><pre><code><code>{
  "deviceId": "DEV123",
  "latitude": 12.9716,
  "longitude": 77.5946,
  "speed": 45,
  "lastUpdatedAt": "2026-01-01T10:10:00Z"
}</code></code></pre><p>Partition Key:</p><pre><code></code></pre><pre><code><code>deviceId</code></code></pre><p>Database:</p><pre><code></code></pre><pre><code><code>Redis</code></code></pre><div><hr></div><h2>Location History Table</h2><pre><code></code></pre><pre><code><code>{
  "deviceId": "DEV123",
  "timestamp": 1745000000,
  "latitude": 12.9716,
  "longitude": 77.5946,
  "speed": 45
}</code></code></pre><p>Partition Key:</p><pre><code></code></pre><pre><code><code>deviceId</code></code></pre><p>Sort Key:</p><pre><code></code></pre><pre><code><code>timestamp</code></code></pre><p>Database:</p><pre><code></code></pre><pre><code><code>Cassandra</code></code></pre><div><hr></div><h2>Geofence Table</h2><pre><code></code></pre><pre><code><code>{
  "geofenceId": "GF123",
  "name": "Warehouse",
  "centerLatitude": 12.9716,
  "centerLongitude": 77.5946,
  "radiusMeters": 500,
  "createdAt": "2026-01-01T10:00:00Z"
}</code></code></pre><p>Database:</p><pre><code></code></pre><pre><code><code>PostgreSQL</code></code></pre><div><hr></div><h2>Alert Table</h2><pre><code></code></pre><pre><code><code>{
  "alertId": "ALT123",
  "deviceId": "DEV123",
  "alertType": "GEOFENCE_EXIT",
  "message": "Vehicle left warehouse zone",
  "createdAt": "2026-01-01T10:15:00Z"
}</code></code></pre><p>Database:</p><pre><code></code></pre><pre><code><code>PostgreSQL</code></code></pre><div><hr></div><h1>High Level Architecture</h1><pre><code></code></pre><pre><code><code>                +----------------+
                | Mobile Device  |
                | GPS Tracker    |
                +--------+-------+
                         |
                         v
                +----------------+
                | API Gateway    |
                +--------+-------+
                         |
                         v
                +----------------+
                | Tracking       |
                | Service        |
                +--------+-------+
                         |
          +--------------+--------------+
          |                             |
          v                             v

 +----------------+         +-------------------+
 | Redis Current  |         | Kafka             |
 | Location Cache |         | Location Stream   |
 +----------------+         +---------+---------+
                                      |
                                      |
             +------------------------+------------------+
             |                                           |
             v                                           v

   +-------------------+                     +------------------+
   | Location History  |                     | Geofence Engine  |
   | Service           |                     | Service          |
   +--------+----------+                     +--------+---------+
            |                                         |
            v                                         v

      +------------+                          +--------------+
      | Cassandra  |                          | Alert Service|
      +------------+                          +------+-------+
                                                      |
                                                      v
                                            +------------------+
                                            | Notification     |
                                            | Service          |
                                            +------------------+</code></code></pre><div><hr></div><h1>Microservices</h1><h2>1. Device Service</h2><p>Responsibilities:</p><ul><li><p>Device registration<br></p></li><li><p>Device lifecycle management<br></p></li><li><p>Device metadata storage<br></p></li></ul><p>Database:</p><pre><code></code></pre><pre><code><code>PostgreSQL</code></code></pre><div><hr></div><h2>2. Tracking Service</h2><p>Responsibilities:</p><ul><li><p>Receive GPS updates<br></p></li><li><p>Validate payload<br></p></li><li><p>Publish events to Kafka<br></p></li></ul><p>Database:</p><pre><code></code></pre><pre><code><code>Redis</code></code></pre><div><hr></div><h2>3. Location History Service</h2><p>Responsibilities:</p><ul><li><p>Persist location updates<br></p></li><li><p>Historical queries<br></p></li></ul><p>Database:</p><pre><code></code></pre><pre><code><code>Cassandra</code></code></pre><div><hr></div><h2>4. Geofence Service</h2><p>Responsibilities:</p><ul><li><p>Geofence creation<br></p></li><li><p>Entry/exit detection<br></p></li></ul><p>Database:</p><pre><code></code></pre><pre><code><code>PostgreSQL</code></code></pre><div><hr></div><h2>5. Alert Service</h2><p>Responsibilities:</p><ul><li><p>Generate alerts<br></p></li><li><p>Store alert history<br></p></li></ul><p>Database:</p><pre><code></code></pre><pre><code><code>PostgreSQL</code></code></pre><div><hr></div><h2>6. Notification Service</h2><p>Responsibilities:</p><ul><li><p>SMS notifications<br></p></li><li><p>Email notifications<br></p></li><li><p>Push notifications<br></p></li></ul><p>Database:</p><pre><code></code></pre><pre><code><code>None (Stateless)</code></code></pre><div><hr></div><h1>End-to-End Flow</h1><pre><code></code></pre><pre><code><code>1. GPS Device sends location update.

2. API Gateway forwards request to Tracking Service.

3. Tracking Service:
   - Validates request
   - Updates Redis current location
   - Publishes LocationEvent to Kafka

4. Location History Service consumes event.
   - Stores event in Cassandra

5. Geofence Service consumes event.
   - Checks geofence rules

6. If breach detected:
   - Generate Alert Event

7. Alert Service stores alert.

8. Notification Service sends SMS/Email/Push.

9. Dashboard fetches:
   - Current location from Redis
   - Historical route from Cassandra
   - Alerts from PostgreSQL</code></code></pre><h3>Scale Estimation</h3><pre><code></code></pre><pre><code><code>10 Million Devices

Average Update Frequency = 30 seconds

Writes/sec
= 10,000,000 / 30
&#8776; 333,000 writes/sec

Daily Location Records
&#8776; 28 Billion records/day

Storage Choice:
- Redis -&gt; Current State
- Kafka -&gt; Streaming
- Cassandra -&gt; Time Series History
- PostgreSQL -&gt; Metadata &amp; Alerts</code></code></pre><p>This design is suitable for a logistics, fleet-management, package-tracking, or IoT tracking platform operating at internet scale.</p>]]></content:encoded></item><item><title><![CDATA[HLD: Design a distributed search system that indexes 1 million files and supports querying files containing a given word]]></title><description><![CDATA[If you&#8217;re looking for paid 1:1 mentorship with a strong focus on LLD (core emphasis on Multithreading), HLD, DSA, and system design research papers, feel free to reach out.]]></description><link>https://programmingappliedai.substack.com/p/hld-design-a-distributed-search-system</link><guid isPermaLink="false">https://programmingappliedai.substack.com/p/hld-design-a-distributed-search-system</guid><dc:creator><![CDATA[Shashank Mishra]]></dc:creator><pubDate>Mon, 08 Jun 2026 17:16:31 GMT</pubDate><enclosure url="iframe.php?url=https%3A%2F%2Fsubstackcdn.com%2Fimage%2Ffetch%2F%24s_%21riGX%21%2Cw_256%2Cc_limit%2Cf_auto%2Cq_auto%3Agood%2Cfl_progressive%3Asteep%2Fhttps%253A%252F%252Fsubstack-post-media.s3.amazonaws.com%252Fpublic%252Fimages%252F58e132e8-cd28-4037-b0ef-feabb2b68221_144x144.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h3><strong>If you&#8217;re looking for paid 1:1 mentorship with a strong focus on LLD (core emphasis on Multithreading), HLD, DSA, and system design research papers, feel free to reach out.</strong></h3><p>&#128233; <strong>Contact:</strong> programmingappliedai@gmail.com</p><p>Example:</p><p>Search Query: <code>"red"</code><br>Expected Output: List of all file IDs/names containing the word <code>"red"</code>.</p><p>Traffic:</p><ul><li><p>~10 lakh requests/day (~11.5 requests/sec average)</p></li><li><p>Assume:</p><ul><li><p>Exact keyword matching only</p></li><li><p>No typo tolerance</p></li><li><p>Words contain only <code>a-z</code></p></li><li><p>Files can be added/updated periodically</p></li></ul></li></ul><div><hr></div><h1>Functional Requirements (FR)</h1><h3>FR1. File Ingestion</h3><p>System should accept and process files for indexing.</p><div><hr></div><h3>FR2. Word Extraction &amp; Tokenization</h3><p>System should parse files and extract normalized words (<code>a-z</code> only).</p><div><hr></div><h3>FR3. Inverted Index Creation</h3><p>System should maintain an inverted index mapping:</p><pre><code></code></pre><pre><code><code>word &#8594; list of file_ids</code></code></pre><p>Example:</p><pre><code></code></pre><pre><code><code>red &#8594; [file1, file8, file20]</code></code></pre><div><hr></div><h3>FR4. Search API</h3><p>User should be able to search for a word and retrieve all matching files.</p><div><hr></div><h3>FR5. Incremental Updates</h3><p>System should support:</p><ul><li><p>New file addition<br></p></li><li><p>File modification<br></p></li><li><p>File deletion<br><br>without rebuilding the complete index.<br></p></li></ul><div><hr></div><h1>Non-Functional Requirements (NFR)</h1><h3>NFR1. Low Latency</h3><p>Search response time should be under 100ms.</p><div><hr></div><h3>NFR2. High Availability</h3><p>Search service should remain available during node failures.</p><div><hr></div><h3>NFR3. Scalability</h3><p>System should scale horizontally as:</p><ul><li><p>Number of files increases<br></p></li><li><p>Query traffic increases<br></p></li></ul><div><hr></div><h3>NFR4. Durability</h3><p>Indexed metadata and file mappings should not be lost.</p><div><hr></div><h3>NFR5. Efficient Storage</h3><p>Index storage should be optimized using compression and deduplication.</p><div><hr></div><h1>High Level Architecture</h1><pre><code></code></pre><pre><code><code>                +------------------+
                |   Client/User    |
                +--------+---------+
                         |
                         v
               +---------+----------+
               |   Search API Layer |
               +---------+----------+
                         |
              +----------+-----------+
              |                      |
              v                      v
     +--------+-------+      +-------+--------+
     |   Query Cache  |      | Search Service |
     |    (Redis)     |      +-------+--------+
     +----------------+              |
                                     v
                          +----------+----------+
                          |   Inverted Index    |
                          |  (ElasticSearch /  |
                          |    Lucene Index)   |
                          +----------+----------+
                                     |
                  +------------------+------------------+
                  |                                     |
                  v                                     v
        +---------+---------+             +-------------+----------+
        | Index Builder     |             | Metadata DB            |
        | Tokenizer Engine  |             | (File Metadata Store)  |
        +---------+---------+             +------------------------+
                  |
                  v
         +--------+--------+
         | Distributed File |
         | Storage (S3/HDFS)|
         +------------------+</code></code></pre><div><hr></div><h1>Core Idea &#8212; Inverted Index</h1><p>Traditional search over 1 million files is expensive:</p><pre><code></code></pre><pre><code><code>For every query:
   Scan all files</code></code></pre><p>Complexity:</p><pre><code></code></pre><pre><code><code>O(number_of_files)</code></code></pre><p>Instead, build an inverted index.</p><div><hr></div><h2>Inverted Index Structure</h2><pre><code></code></pre><pre><code><code>{
   "red"  : [1, 7, 10, 55],
   "blue" : [2, 3, 10],
   "car"  : [5, 6]
}</code></code></pre><p>Search becomes:</p><pre><code></code></pre><pre><code><code>Lookup(word)</code></code></pre><p>Complexity:</p><pre><code></code></pre><pre><code><code>O(1) or O(logN)</code></code></pre><p>depending on storage engine.</p><div><hr></div><h1>Components</h1><h2>1. File Storage Service</h2><p>Stores original files.</p><p>Possible storage:</p><ul><li><p>HDFS<br></p></li><li><p>S3<br></p></li><li><p>Blob storage<br></p></li></ul><p>Each file gets:</p><pre><code></code></pre><pre><code><code>{
  "file_id": "f123",
  "path": "/docs/a.txt",
  "uploaded_at": 1712345678
}</code></code></pre><div><hr></div><h1>2. File Ingestion Service</h1><p>Responsible for:</p><ul><li><p>Accepting files<br></p></li><li><p>Sending indexing jobs to queue<br></p></li></ul><p>Flow:</p><pre><code></code></pre><pre><code><code>Upload File
    &#8595;
Generate file_id
    &#8595;
Push indexing job to Kafka/SQS</code></code></pre><div><hr></div><h1>3. Tokenizer / Parser Service</h1><p>Reads file contents and extracts words.</p><p>Steps:</p><ul><li><p>Lowercase conversion<br></p></li><li><p>Remove punctuation<br></p></li><li><p>Split into words<br></p></li></ul><p>Example:</p><pre><code></code></pre><pre><code><code>"The Red Car"</code></code></pre><p>becomes:</p><pre><code></code></pre><pre><code><code>["the", "red", "car"]</code></code></pre><div><hr></div><h1>4. Index Builder</h1><p>Builds inverted index.</p><p>Example:</p><pre><code></code></pre><pre><code><code>file1 -&gt; ["red", "car"]

Index:
red -&gt; file1
car -&gt; file1</code></code></pre><div><hr></div><h1>5. Search Service</h1><p>Handles user queries.</p><p>Flow:</p><ol><li><p>Receive query <code>"red"</code><br></p></li><li><p>Check Redis cache<br></p></li><li><p>Lookup inverted index<br></p></li><li><p>Return matching files<br></p></li></ol><div><hr></div><h1>Database Design</h1><h2>A. File Metadata Table</h2><pre><code></code></pre><pre><code><code>{
  "file_id": "string",
  "file_name": "string",
  "storage_path": "string",
  "uploaded_at": "timestamp",
  "version": "int",
  "status": "ACTIVE | DELETED"
}</code></code></pre><p>Database:</p><ul><li><p>PostgreSQL<br><br>or<br></p></li><li><p>MySQL<br></p></li></ul><div><hr></div><h2>B. Inverted Index Storage</h2><h3>Logical Schema</h3><pre><code></code></pre><pre><code><code>{
  "word": "red",
  "document_frequency": 1200,
  "posting_list": [
    "file1",
    "file8",
    "file20"
  ]
}</code></code></pre><p>Preferred technologies:</p><ul><li><p>ElasticSearch<br></p></li><li><p>Apache Lucene<br></p></li><li><p>OpenSearch<br></p></li></ul><div><hr></div><h1>Search Flow</h1><pre><code></code></pre><pre><code><code>User Searches "red"
        |
        v
Search API
        |
        v
Redis Cache Check
   |          |
Hit          Miss
 |             |
Return      Query Index
                 |
                 v
        Get Posting List
                 |
                 v
         Fetch Metadata
                 |
                 v
            Return Files</code></code></pre><div><hr></div><h1>File Indexing Flow</h1><pre><code></code></pre><pre><code><code>File Upload
    |
    v
Ingestion Service
    |
    v
Message Queue (Kafka)
    |
    v
Indexer Worker
    |
    v
Tokenizer
    |
    v
Update Inverted Index</code></code></pre><div><hr></div><h1>Scaling Strategy</h1><h2>Read Scaling</h2><p>Search traffic is read-heavy.</p><p>Use:</p><ul><li><p>Multiple search replicas<br></p></li><li><p>Load balancer<br></p></li><li><p>Redis cache<br></p></li></ul><div><hr></div><h2>Index Partitioning (Sharding)</h2><p>Partition words alphabetically:</p><pre><code></code></pre><pre><code><code>a-f  &#8594; shard1
g-l  &#8594; shard2
m-r  &#8594; shard3
s-z  &#8594; shard4</code></code></pre><p>or use:</p><ul><li><p>Consistent hashing<br></p></li></ul><div><hr></div><h1>Caching Strategy</h1><p>Popular searches cached in Redis.</p><p>Example:</p><pre><code></code></pre><pre><code><code>key   = "red"
value = [file1, file2, file8]
TTL   = 10 mins</code></code></pre><p>Reduces repeated index lookups.</p><div><hr></div><h1>Estimation</h1><h2>Requests</h2><pre><code></code></pre><pre><code><code>10 lakh/day
&#8776; 11.5 req/sec average
Peak &#8776; 100-200 req/sec</code></code></pre><p>Very manageable with:</p><ul><li><p>Redis<br></p></li><li><p>ElasticSearch cluster<br></p></li></ul><div><hr></div><h1>Fault Tolerance</h1><h2>Replication</h2><p>Maintain:</p><ul><li><p>Replica index shards<br></p></li><li><p>Multi-node search cluster<br></p></li></ul><div><hr></div><h2>Queue Durability</h2><p>Kafka persists indexing jobs.</p><p>If indexer crashes:</p><ul><li><p>Job replay possible<br></p></li></ul><div><hr></div><h1>Optimizations</h1><h2>1. Compression</h2><p>Store posting lists using:</p><ul><li><p>Delta encoding<br></p></li><li><p>Bitmaps<br></p></li></ul><div><hr></div><h2>2. Skip Lists</h2><p>Improve search traversal for large posting lists.</p><div><hr></div><h2>3. Batch Indexing</h2><p>Instead of updating index per file:</p><ul><li><p>Batch updates every few seconds.<br></p></li></ul><div><hr></div><h1>Bottlenecks</h1><h2>Hot Keywords</h2><p>Words like:</p><pre><code></code></pre><pre><code><code>the, is, and</code></code></pre><p>can have huge posting lists.</p><p>Solution:</p><ul><li><p>Stop-word filtering<br></p></li><li><p>Compressed bitmaps<br></p></li></ul><div><hr></div><h1>Technologies</h1><div class="highlighted_code_block" data-attrs="{&quot;language&quot;:&quot;plaintext&quot;,&quot;nodeId&quot;:&quot;cec65cfa-f84d-4109-bc8d-c965843d5924&quot;}" data-component-name="HighlightedCodeBlockToDOM"><pre class="shiki"><code class="language-plaintext">| Component     | Technology            |
| ------------- | --------------------- |
| API Layer     | Go / Java Spring Boot |
| Queue         | Kafka                 |
| Cache         | Redis                 |
| Search Engine | ElasticSearch         |
| Metadata DB   | PostgreSQL            |
| Storage       | S3 / HDFS             |
</code></pre></div><div><hr></div><h1>Final Design Summary</h1><p>The system uses an inverted index to efficiently map:</p><pre><code></code></pre><pre><code><code>word &#8594; files</code></code></pre><p>Core benefits:</p><ul><li><p>Fast lookup<br></p></li><li><p>Horizontal scalability<br></p></li><li><p>Incremental indexing<br></p></li><li><p>Low latency search<br></p></li></ul><p>The architecture separates:</p><ul><li><p>File storage<br></p></li><li><p>Index building<br></p></li><li><p>Search serving<br></p></li></ul><p>allowing the system to scale independently for ingestion and querying.</p>]]></content:encoded></item><item><title><![CDATA[HLD: Design a system that levies penalties or taxes on riders/drivers based on constraints like completing a minimum number of rides per month or getting below-average ratings.]]></title><description><![CDATA[If you&#8217;re looking for paid 1:1 mentorship with a strong focus on LLD (core emphasis on Multithreading), HLD, DSA, and system design research papers, feel free to reach out.]]></description><link>https://programmingappliedai.substack.com/p/hld-design-a-system-that-levies-penalties</link><guid isPermaLink="false">https://programmingappliedai.substack.com/p/hld-design-a-system-that-levies-penalties</guid><dc:creator><![CDATA[Shashank Mishra]]></dc:creator><pubDate>Tue, 26 May 2026 18:23:40 GMT</pubDate><enclosure url="iframe.php?url=https%3A%2F%2Fsubstackcdn.com%2Fimage%2Ffetch%2F%24s_%21riGX%21%2Cw_256%2Cc_limit%2Cf_auto%2Cq_auto%3Agood%2Cfl_progressive%3Asteep%2Fhttps%253A%252F%252Fsubstack-post-media.s3.amazonaws.com%252Fpublic%252Fimages%252F58e132e8-cd28-4037-b0ef-feabb2b68221_144x144.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h3><strong>If you&#8217;re looking for paid 1:1 mentorship with a strong focus on LLD (core emphasis on Multithreading), HLD, DSA, and system design research papers, feel free to reach out.</strong></h3><p>&#128233; <strong>Contact:</strong> programmingappliedai@gmail.com</p><h2>Functional Requirements (FR)</h2><ol><li><p><strong>Penalty/Tax Rule Management</strong><br>System should allow admins to define and manage dynamic rules for penalties/taxes based on:</p><ul><li><p>Minimum rides completed</p></li><li><p>Cancellation rate</p></li><li><p>Average rider/driver ratings</p></li><li><p>Inactive days</p></li><li><p>Peak-hour participation</p></li><li><p>Fraud signals</p></li></ul></li><li><p><strong>Periodic Evaluation Engine</strong><br>System should periodically evaluate riders/drivers (daily/weekly/monthly) against configured rules and determine applicable penalties or taxes.</p></li><li><p><strong>Penalty Calculation &amp; Ledger Management</strong><br>System should calculate penalty amounts accurately and maintain a financial ledger/history for every deduction, adjustment, refund, or waiver.</p></li><li><p><strong>Notification &amp; Transparency</strong><br>Users should receive notifications explaining:</p><ul><li><p>Why the penalty was applied</p></li><li><p>Rule violated</p></li><li><p>Amount deducted</p></li><li><p>Appeal process</p></li><li><p>Deadline for compliance</p></li></ul></li><li><p><strong>Appeal &amp; Dispute Handling</strong><br>Riders/drivers should be able to raise disputes against penalties, upload proofs, and track appeal status through the platform.</p></li></ol><div><hr></div><h2>Non-Functional Requirements (NFR)</h2><ol><li><p><strong>Scalability</strong><br>System should support millions of riders/drivers and evaluate penalties for large datasets efficiently during monthly batch processing.</p></li><li><p><strong>High Availability</strong><br>Critical services like rule evaluation, deductions, and notifications should maintain high availability (99.9%+) to avoid financial inconsistencies.</p></li><li><p><strong>Consistency &amp; Accuracy</strong><br>Financial calculations and deductions must be strongly consistent to prevent duplicate or incorrect penalties.</p></li><li><p><strong>Extensibility</strong><br>System should support adding new penalty rules and policy types without requiring major architectural changes.</p></li><li><p><strong>Auditability &amp; Compliance</strong><br>Every rule evaluation, deduction, override, and admin action should be fully auditable for regulatory and legal compliance.</p></li></ol><h1>APIs for Penalty/Tax Enforcement System</h1><div><hr></div><h2>1. Create Penalty Rule</h2><h3>API</h3><p><code>POST /api/v1/rules</code></p><h3>Request</h3><pre><code></code></pre><pre><code><code>{
  "ruleName": "Minimum Monthly Ride Rule",
  "entityType": "DRIVER",
  "condition": {
    "metric": "MONTHLY_RIDES",
    "operator": "LESS_THAN",
    "value": 100
  },
  "penalty": {
    "type": "FIXED",
    "amount": 500
  },
  "evaluationFrequency": "MONTHLY",
  "isActive": true
}</code></code></pre><h3>Response</h3><pre><code></code></pre><pre><code><code>{
  "ruleId": "RULE_12345",
  "status": "CREATED",
  "createdAt": "2026-05-26T10:00:00Z"
}</code></code></pre><div><hr></div><h2>2. Evaluate User Eligibility for Penalty</h2><h3>API</h3><p><code>POST /api/v1/evaluations/run</code></p><h3>Request</h3><pre><code></code></pre><pre><code><code>{
  "entityType": "DRIVER",
  "entityId": "DRIVER_789",
  "evaluationPeriod": "2026-05"
}</code></code></pre><h3>Response</h3><pre><code></code></pre><pre><code><code>{
  "entityId": "DRIVER_789",
  "evaluationPeriod": "2026-05",
  "violations": [
    {
      "ruleId": "RULE_12345",
      "metricValue": 72,
      "expectedValue": 100,
      "penaltyAmount": 500
    }
  ],
  "totalPenalty": 500,
  "status": "PENALTY_APPLIED"
}</code></code></pre><div><hr></div><h2>3. Fetch Penalty History</h2><h3>API</h3><p><code>GET /api/v1/penalties/{entityId}</code></p><h3>Response</h3><pre><code></code></pre><pre><code><code>{
  "entityId": "DRIVER_789",
  "penalties": [
    {
      "penaltyId": "PEN_1001",
      "ruleId": "RULE_12345",
      "amount": 500,
      "status": "DEDUCTED",
      "createdAt": "2026-05-26T12:00:00Z"
    },
    {
      "penaltyId": "PEN_1002",
      "ruleId": "RULE_99999",
      "amount": 200,
      "status": "WAIVED",
      "createdAt": "2026-04-26T12:00:00Z"
    }
  ]
}</code></code></pre><div><hr></div><h2>4. Deduct Penalty from Wallet</h2><h3>API</h3><p><code>POST /api/v1/wallets/deduct</code></p><h3>Request</h3><pre><code></code></pre><pre><code><code>{
  "entityId": "DRIVER_789",
  "penaltyId": "PEN_1001",
  "amount": 500,
  "currency": "INR"
}</code></code></pre><h3>Response</h3><pre><code></code></pre><pre><code><code>{
  "transactionId": "TXN_56789",
  "walletBalance": 3200,
  "status": "SUCCESS"
}</code></code></pre><div><hr></div><h2>5. Raise Penalty Dispute</h2><h3>API</h3><p><code>POST /api/v1/disputes</code></p><h3>Request</h3><pre><code></code></pre><pre><code><code>{
  "penaltyId": "PEN_1001",
  "entityId": "DRIVER_789",
  "reason": "Ride count calculation incorrect",
  "attachments": [
    "s3://proofs/screenshot1.png"
  ]
}</code></code></pre><h3>Response</h3><pre><code></code></pre><pre><code><code>{
  "disputeId": "DISP_4567",
  "status": "UNDER_REVIEW",
  "createdAt": "2026-05-26T13:00:00Z"
}</code></code></pre><div><hr></div><h2>6. Get Evaluation Summary Dashboard</h2><h3>API</h3><p><code>GET /api/v1/reports/summary?period=2026-05</code></p><h3>Response</h3><pre><code></code></pre><pre><code><code>{
  "period": "2026-05",
  "totalDriversEvaluated": 1000000,
  "totalPenaltiesApplied": 125000,
  "totalAmountCollected": 45000000,
  "topViolationReasons": [
    {
      "rule": "MIN_MONTHLY_RIDES",
      "count": 80000
    },
    {
      "rule": "LOW_RATING",
      "count": 45000
    }
  ]
}</code></code></pre><p></p><p><strong>Databases and Schema</strong></p><div class="highlighted_code_block" data-attrs="{&quot;language&quot;:&quot;plaintext&quot;,&quot;nodeId&quot;:&quot;060d05ef-6574-4d03-b609-c36ef225043b&quot;}" data-component-name="HighlightedCodeBlockToDOM"><pre class="shiki"><code class="language-plaintext">```json
{
  "users": {
    "user_id": "BIGINT",
    "user_type": "ENUM(DRIVER, RIDER)",
    "name": "VARCHAR",
    "avg_rating": "DECIMAL(2,1)",
    "total_rides": "BIGINT",
    "wallet_balance": "DECIMAL",
    "status": "ENUM(ACTIVE, BLOCKED)",
    "created_at": "TIMESTAMP"
  },

  "penalty_rules": {
    "rule_id": "BIGINT",
    "rule_name": "VARCHAR",
    "entity_type": "ENUM(DRIVER, RIDER)",
    "metric": "VARCHAR",
    "operator": "ENUM(LESS_THAN, GREATER_THAN)",
    "threshold_value": "DECIMAL",
    "penalty_type": "ENUM(FIXED, PERCENTAGE)",
    "penalty_amount": "DECIMAL",
    "evaluation_frequency": "ENUM(DAILY, WEEKLY, MONTHLY)",
    "is_active": "BOOLEAN",
    "created_by": "BIGINT",
    "created_at": "TIMESTAMP"
  },

  "user_metrics": {
    "metric_id": "BIGINT",
    "user_id": "BIGINT",
    "month": "VARCHAR",
    "completed_rides": "INT",
    "cancelled_rides": "INT",
    "avg_rating": "DECIMAL(2,1)",
    "online_hours": "INT",
    "last_updated_at": "TIMESTAMP"
  },

  "penalties": {
    "penalty_id": "BIGINT",
    "user_id": "BIGINT",
    "rule_id": "BIGINT",
    "metric_value": "DECIMAL",
    "expected_value": "DECIMAL",
    "penalty_amount": "DECIMAL",
    "status": "ENUM(APPLIED, DEDUCTED, WAIVED)",
    "evaluation_period": "VARCHAR",
    "created_at": "TIMESTAMP"
  },

  "wallet_transactions": {
    "transaction_id": "BIGINT",
    "user_id": "BIGINT",
    "penalty_id": "BIGINT",
    "transaction_type": "ENUM(DEBIT, CREDIT)",
    "amount": "DECIMAL",
    "balance_after_txn": "DECIMAL",
    "transaction_status": "ENUM(SUCCESS, FAILED)",
    "created_at": "TIMESTAMP"
  },

  "disputes": {
    "dispute_id": "BIGINT",
    "penalty_id": "BIGINT",
    "user_id": "BIGINT",
    "reason": "TEXT",
    "attachment_url": "VARCHAR",
    "status": "ENUM(UNDER_REVIEW, APPROVED, REJECTED)",
    "resolved_by": "BIGINT",
    "resolution_notes": "TEXT",
    "created_at": "TIMESTAMP",
    "resolved_at": "TIMESTAMP"
  },

  "audit_logs": {
    "audit_id": "BIGINT",
    "entity_type": "VARCHAR",
    "entity_id": "BIGINT",
    "action": "VARCHAR",
    "performed_by": "BIGINT",
    "old_value": "JSON",
    "new_value": "JSON",
    "created_at": "TIMESTAMP"
  }
}
```

</code></pre></div><p></p><p>HLD</p><div class="highlighted_code_block" data-attrs="{&quot;language&quot;:&quot;plaintext&quot;,&quot;nodeId&quot;:&quot;9b37668f-f661-40e7-aa85-3212e0f3d38a&quot;}" data-component-name="HighlightedCodeBlockToDOM"><pre class="shiki"><code class="language-plaintext">```text
========================================================
HIGH LEVEL DESIGN (HLD)
========================================================

                    +----------------------+
                    |      Admin Panel     |
                    +----------+-----------+
                               |
                               v
                    +----------------------+
                    |   Rule Management    |
                    |      Service         |
                    +----------+-----------+
                               |
                               v
                    +----------------------+
                    |   Penalty Rules DB   |
                    +----------------------+



+------------+       +----------------------+       +------------------+
| Ride       | ----&gt; |  Event Ingestion     | ----&gt; | Kafka/Event Bus  |
| Service    |       |  Service             |       +--------+---------+
+------------+       +----------------------+                |
                                                             |
+------------+                                               |
| Rating     | ----------------------------------------------+
| Service    |                                               |
+------------+                                               |
                                                             v

                                                +----------------------+
                                                | Metrics Aggregator   |
                                                | Service              |
                                                +----------+-----------+
                                                           |
                                                           v
                                                +----------------------+
                                                | User Metrics DB      |
                                                +----------+-----------+
                                                           |
                                                           v

                                                +----------------------+
                                                | Penalty Evaluation   |
                                                | Engine               |
                                                +----------+-----------+
                                                           |
                                      +--------------------+------------------+
                                      |                                       |
                                      v                                       v

                        +--------------------------+         +------------------------+
                        | Penalty Ledger Service   |         | Notification Service   |
                        +------------+-------------+         +------------+-----------+
                                     |                                     |
                                     v                                     v

                        +--------------------------+         +------------------------+
                        | Penalty DB               |         | Email/SMS/Push         |
                        +------------+-------------+         +------------------------+
                                     |
                                     v

                        +--------------------------+
                        | Wallet Service           |
                        +------------+-------------+
                                     |
                                     v

                        +--------------------------+
                        | Wallet Transactions DB   |
                        +--------------------------+



========================================================
FLOW DIAGRAM - MONTHLY PENALTY EVALUATION
========================================================

1. Ride Completed
        |
        v
2. Ride Service emits event to Kafka
        |
        v
3. Metrics Aggregator consumes events
        |
        v
4. Update monthly metrics in User Metrics DB
        |
        v
5. Monthly Scheduler triggers Evaluation Engine
        |
        v
6. Evaluation Engine fetches:
       - Active Rules
       - User Metrics
        |
        v
7. Rule Validation
       Example:
       completed_rides &lt; 100
        |
        +---- NO ----&gt; No action
        |
        +---- YES ---&gt; Generate penalty
                             |
                             v
8. Store penalty in Penalty DB
                             |
                             v
9. Call Wallet Service
                             |
                             v
10. Deduct amount from wallet
                             |
                             v
11. Store wallet transaction
                             |
                             v
12. Send notification to user



========================================================
FLOW DIAGRAM - DISPUTE HANDLING
========================================================

1. User raises dispute
        |
        v
2. Dispute Service stores dispute
        |
        v
3. Admin reviews dispute
        |
        +---- APPROVED ----+
        |                  |
        |                  v
        |          Refund penalty
        |                  |
        |                  v
        |          Update wallet balance
        |
        +---- REJECTED ----+
                           |
                           v
                    Keep penalty active
                           |
                           v
                    Notify user



========================================================
CORE MICROSERVICES
========================================================

1. Rule Management Service
   - Create/update/delete rules
   - Rule versioning

2. Metrics Aggregator Service
   - Consume ride/rating events
   - Aggregate monthly metrics

3. Penalty Evaluation Engine
   - Execute rule evaluation jobs
   - Generate penalties

4. Penalty Ledger Service
   - Maintain immutable penalty history

5. Wallet Service
   - Deduct/refund money
   - Ensure transactional consistency

6. Notification Service
   - SMS/Push/Email alerts

7. Dispute Service
   - Dispute lifecycle management

8. Audit Service
   - Maintain compliance logs



========================================================
SCALABILITY CONSIDERATIONS
========================================================

1. Kafka partitions by user_id

2. Batch evaluation jobs partitioned by region/user buckets

3. Redis cache for active rules

4. Read replicas for analytics queries

5. Monthly partitioned tables for penalties and transactions

6. Idempotent wallet deduction APIs

7. Retry queues + DLQ for failed deductions
```</code></pre></div><p></p><div class="highlighted_code_block" data-attrs="{&quot;language&quot;:&quot;plaintext&quot;,&quot;nodeId&quot;:&quot;8b7b5b51-ec36-4bca-8e54-ec609641f1b0&quot;}" data-component-name="HighlightedCodeBlockToDOM"><pre class="shiki"><code class="language-plaintext">========================================================
MICROSERVICES AND INTERACTIONS
========================================================

1. API GATEWAY
--------------------------------------------------------
Responsibilities:
- Entry point for all clients
- Authentication &amp; authorization
- Rate limiting
- Request routing

Interacts With:
- Rule Management Service
- Penalty Service
- Dispute Service
- Wallet Service
- Notification Service



2. RULE MANAGEMENT SERVICE
--------------------------------------------------------
Responsibilities:
- Create/update/delete penalty rules
- Enable/disable rules
- Rule versioning
- Rule validation

Database:
- penalty_rules DB

Publishes Events:
- RULE_CREATED
- RULE_UPDATED
- RULE_DELETED

Interacts With:
- Admin Panel
- Penalty Evaluation Engine
- Redis Cache



3. EVENT INGESTION SERVICE
--------------------------------------------------------
Responsibilities:
- Consume ride/rating/cancellation events
- Standardize incoming events
- Push events to Kafka

Consumes From:
- Ride Service
- Rating Service

Publishes To:
- Kafka Topics



4. METRICS AGGREGATOR SERVICE
--------------------------------------------------------
Responsibilities:
- Consume Kafka events
- Aggregate monthly metrics
- Compute:
   - completed rides
   - cancellation %
   - avg ratings
   - active hours

Database:
- user_metrics DB

Consumes:
- ride_completed events
- rating_updated events
- cancellation events

Publishes:
- METRICS_UPDATED



5. PENALTY EVALUATION ENGINE
--------------------------------------------------------
Responsibilities:
- Run periodic evaluation jobs
- Fetch active rules
- Evaluate user metrics
- Generate penalties

Consumes:
- METRICS_UPDATED
- Scheduler triggers

Reads From:
- penalty_rules DB
- user_metrics DB

Publishes:
- PENALTY_CREATED

Interacts With:
- Penalty Ledger Service
- Wallet Service
- Notification Service



6. PENALTY LEDGER SERVICE
--------------------------------------------------------
Responsibilities:
- Store immutable penalty history
- Maintain audit trail
- Penalty state management

Database:
- penalties DB

Consumes:
- PENALTY_CREATED

Publishes:
- PENALTY_APPLIED
- PENALTY_WAIVED

Interacts With:
- Wallet Service
- Dispute Service
- Audit Service



7. WALLET SERVICE
--------------------------------------------------------
Responsibilities:
- Deduct penalty amount
- Refund amount on dispute approval
- Maintain financial consistency
- Handle retries/idempotency

Database:
- wallet_transactions DB

Consumes:
- PENALTY_APPLIED
- REFUND_REQUESTED

Publishes:
- PAYMENT_SUCCESS
- PAYMENT_FAILED

Interacts With:
- Penalty Service
- Notification Service



8. NOTIFICATION SERVICE
--------------------------------------------------------
Responsibilities:
- Send push/email/SMS notifications
- Notify about:
   - penalties
   - refunds
   - disputes
   - warnings

Consumes:
- PENALTY_CREATED
- PAYMENT_SUCCESS
- DISPUTE_RESOLVED

External Integrations:
- Email provider
- SMS gateway
- Push notification provider



9. DISPUTE SERVICE
--------------------------------------------------------
Responsibilities:
- Create/manage disputes
- Upload proof documents
- Track dispute lifecycle

Database:
- disputes DB

Consumes:
- User dispute requests

Publishes:
- DISPUTE_CREATED
- DISPUTE_APPROVED
- DISPUTE_REJECTED

Interacts With:
- Penalty Ledger Service
- Wallet Service
- Notification Service



10. AUDIT SERVICE
--------------------------------------------------------
Responsibilities:
- Track all admin/system actions
- Maintain compliance logs
- Store immutable audit records

Database:
- audit_logs DB

Consumes:
- RULE_UPDATED
- PENALTY_APPLIED
- DISPUTE_RESOLVED
- WALLET_DEDUCTED



========================================================
SERVICE INTERACTION FLOW
========================================================

Ride Service
     |
     v
Event Ingestion Service
     |
     v
Kafka/Event Bus
     |
     v
Metrics Aggregator Service
     |
     v
User Metrics DB
     |
     v
Penalty Evaluation Engine
     |
     +--------------------+
     |                    |
     v                    v
Penalty Ledger      Notification Service
Service
     |
     v
Wallet Service
     |
     v
Wallet Transactions DB
     |
     v
Notification Service



========================================================
ASYNC COMMUNICATION
========================================================

Kafka Topics:
- ride_completed
- ride_cancelled
- rating_updated
- metrics_updated
- penalty_created
- penalty_applied
- payment_success
- dispute_created
- dispute_resolved



========================================================
WHY MICROSERVICE ARCHITECTURE?
========================================================

1. Independent scaling of evaluation engine

2. Wallet service isolated for strong consistency

3. Rule engine can evolve independently

4. Async event-driven processing reduces coupling

5. Easier fault isolation

6. Supports millions of monthly evaluations</code></pre></div><p></p>]]></content:encoded></item><item><title><![CDATA[HLD: Automated Fault Detection & Prevention System (Router Monitoring Platform)(Asked in Microsoft)]]></title><description><![CDATA[Design a scalable platform that continuously monitors routers/network devices, detects anomalies or failures in real time, predicts potential issues, and automatically triggers preventive/remediation.]]></description><link>https://programmingappliedai.substack.com/p/hld-automated-fault-detection-and</link><guid isPermaLink="false">https://programmingappliedai.substack.com/p/hld-automated-fault-detection-and</guid><dc:creator><![CDATA[Shashank Mishra]]></dc:creator><pubDate>Tue, 12 May 2026 16:26:56 GMT</pubDate><enclosure url="iframe.php?url=https%3A%2F%2Fsubstackcdn.com%2Fimage%2Ffetch%2F%24s_%21riGX%21%2Cw_256%2Cc_limit%2Cf_auto%2Cq_auto%3Agood%2Cfl_progressive%3Asteep%2Fhttps%253A%252F%252Fsubstack-post-media.s3.amazonaws.com%252Fpublic%252Fimages%252F58e132e8-cd28-4037-b0ef-feabb2b68221_144x144.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h3><strong>If you&#8217;re looking for paid 1:1 mentorship with a strong focus on LLD (core emphasis on Multithreading), HLD, DSA, and system design research papers, feel free to reach out.</strong></h3><p>&#128233; <strong>Contact:</strong> programmingappliedai@gmail.com</p><p>Example:</p><ul><li><p>Detect high CPU spikes on routers</p></li><li><p>Predict link failures</p></li><li><p>Detect packet drops or abnormal latency</p></li><li><p>Restart interfaces automatically</p></li><li><p>Shift traffic to healthy routes</p></li></ul><div><hr></div><h1>2. Functional Requirements (FR)</h1><h3>1. The system should continuously collect router telemetry such as CPU utilization, memory usage, packet drops, interface statistics, link status, temperature, and logs/SNMP traps at configurable intervals.</h3><p>2. The system should detect failures and anomalies like router downtime, link degradation, interface flapping, traffic anomalies, high latency, and packet loss within a few seconds.</p><p>3. The system should automatically execute preventive or corrective actions such as restarting interfaces, switching routes, triggering failover, throttling traffic, or rebooting unhealthy devices based on predefined policies.</p><p>4. The system should generate alerts and incidents through channels like email, Slack, PagerDuty, and SMS for critical network issues and remediation events.</p><p>5. The system should store historical telemetry and fault data to support trend analysis, root cause analysis, capacity planning, and ML/rule-based failure prediction.</p><div><hr></div><h1>3. Non-Functional Requirements (NFR)</h1><h3>NFR1. High Availability</h3><p>Monitoring system should remain operational even during node failures.</p><p>Target: 99.99% availability.</p><div><hr></div><h3>NFR2. Low Detection Latency</h3><p>Faults should be detected within:</p><ul><li><p>2&#8211;5 seconds for critical failures</p></li><li><p>&lt;1 second for heartbeat failures</p></li></ul><div><hr></div><h3>NFR3. Massive Scalability</h3><p>Support:</p><ul><li><p>Millions of telemetry events/sec</p></li><li><p>100K+ routers</p></li><li><p>Multi-region deployments</p></li></ul><div><hr></div><h3>NFR4. Fault Tolerance</h3><p>No data loss during:</p><ul><li><p>Broker failures</p></li><li><p>Service crashes</p></li><li><p>Network partitions</p></li></ul><div><hr></div><h3>NFR5. Extensibility</h3><p>System should support:</p><ul><li><p>New device types</p></li><li><p>New telemetry protocols</p></li><li><p>Custom remediation plugins</p></li></ul><p>without major redesign.</p><div><hr></div><h1>4. High Level Architecture</h1><pre><code></code></pre><pre><code><code>                 +----------------+
                 |   Admin UI     |
                 +--------+-------+
                          |
                          v
                 +----------------+
                 | API Gateway    |
                 +--------+-------+
                          |
      ------------------------------------------------
      |              |               |               |
      v              v               v               v

+------------+ +-------------+ +-------------+ +--------------+
| Device Mgmt| | Alert Svc   | | Policy Svc  | | Analytics Svc|
+------------+ +-------------+ +-------------+ +--------------+

                          |
                          v

                +------------------+
                | Kafka / Pulsar   |
                +--------+---------+
                         |
     ---------------------------------------------------
     |                 |               |               |
     v                 v               v               v

+------------+ +--------------+ +-------------+ +--------------+
| Collectors | | Detection Svc| | ML Engine   | | Remediation  |
+------------+ +--------------+ +-------------+ +--------------+

                         |
                         v

                 +---------------+
                 | Routers       |
                 +---------------+</code></code></pre><div><hr></div><h1>5. Core Components</h1><h2>A. Telemetry Collectors</h2><p>Responsible for:</p><ul><li><p>SNMP polling<br></p></li><li><p>Streaming telemetry<br></p></li><li><p>Syslog ingestion<br></p></li><li><p>NetFlow/sFlow collection<br></p></li></ul><p>Protocols:</p><ul><li><p>SNMP<br></p></li><li><p>gRPC telemetry<br></p></li><li><p>NETCONF<br></p></li><li><p>SSH<br></p></li><li><p>Syslog<br></p></li></ul><div><hr></div><h2>B. Event Streaming Layer</h2><p>Use:</p><ul><li><p>Apache Kafka<br><br>or<br></p></li><li><p>Apache Pulsar<br></p></li></ul><p>Purpose:</p><ul><li><p>Buffer telemetry<br></p></li><li><p>Decouple services<br></p></li><li><p>Enable replay<br></p></li><li><p>Handle burst traffic<br></p></li></ul><p>Topics:</p><pre><code></code></pre><pre><code><code>telemetry.cpu
telemetry.memory
telemetry.interface
alerts
remediation.tasks</code></code></pre><div><hr></div><h2>C. Detection Engine</h2><p>Performs:</p><ul><li><p>Threshold detection<br></p></li><li><p>Pattern detection<br></p></li><li><p>Correlation<br></p></li><li><p>Stateful analysis<br></p></li></ul><p>Examples:</p><ul><li><p>CPU &gt; 90% for 5 mins<br></p></li><li><p>Packet loss &gt; 20%<br></p></li><li><p>Interface flapping &gt; 5 times/min<br></p></li></ul><p>Techniques:</p><ul><li><p>Rule engine<br></p></li><li><p>CEP (Complex Event Processing)<br></p></li></ul><div><hr></div><h2>D. ML Prediction Engine</h2><p>Predicts:</p><ul><li><p>Link failure probability<br></p></li><li><p>Hardware degradation<br></p></li><li><p>Congestion patterns<br></p></li></ul><p>Models:</p><ul><li><p>Time-series forecasting<br></p></li><li><p>Isolation Forest<br></p></li><li><p>LSTM<br></p></li><li><p>ARIMA<br></p></li></ul><div><hr></div><h2>E. Remediation Service</h2><p>Executes automated actions:</p><ul><li><p>Route failover<br></p></li><li><p>Interface reset<br></p></li><li><p>Restart BGP sessions<br></p></li><li><p>Traffic rerouting<br></p></li></ul><p>Must support:</p><ul><li><p>Rollback<br></p></li><li><p>Audit logs<br></p></li><li><p>Approval workflows<br></p></li></ul><div><hr></div><h2>F. Alerting Service</h2><p>Integrations:</p><ul><li><p>PagerDuty<br></p></li><li><p>Slack<br></p></li><li><p>Email/SMS systems<br></p></li></ul><p>Supports:</p><ul><li><p>Deduplication<br></p></li><li><p>Escalation<br></p></li><li><p>Suppression<br></p></li></ul><div><hr></div><h1>6. APIs</h1><h1>A. Register Router API</h1><h2>Request</h2><pre><code></code></pre><pre><code><code>POST /api/v1/routers</code></code></pre><pre><code></code></pre><pre><code><code>{
  "routerId": "RTR-1001",
  "hostname": "blr-edge-1",
  "ip": "10.0.0.5",
  "location": "Bangalore-DC",
  "vendor": "Cisco",
  "model": "ASR-9000"
}</code></code></pre><h2>Response</h2><pre><code></code></pre><pre><code><code>{
  "status": "REGISTERED",
  "routerId": "RTR-1001"
}</code></code></pre><div><hr></div><h1>B. Push Telemetry API</h1><pre><code></code></pre><pre><code><code>POST /api/v1/telemetry</code></code></pre><h2>Request</h2><pre><code></code></pre><pre><code><code>{
  "routerId": "RTR-1001",
  "timestamp": 1710001231,
  "metrics": {
    "cpu": 91,
    "memory": 72,
    "packetLoss": 15,
    "latency": 240
  }
}</code></code></pre><h2>Response</h2><pre><code></code></pre><pre><code><code>{
  "status": "INGESTED"
}</code></code></pre><div><hr></div><h1>C. Create Remediation Policy</h1><pre><code></code></pre><pre><code><code>POST /api/v1/policies</code></code></pre><h2>Request</h2><pre><code></code></pre><pre><code><code>{
  "policyName": "HighCPURecovery",
  "condition": "cpu &gt; 90 for 5m",
  "action": "restart_interface",
  "severity": "HIGH"
}</code></code></pre><h2>Response</h2><pre><code></code></pre><pre><code><code>{
  "policyId": "POL-101",
  "status": "ACTIVE"
}</code></code></pre><div><hr></div><h1>D. Get Active Alerts</h1><pre><code></code></pre><pre><code><code>GET /api/v1/alerts?severity=CRITICAL</code></code></pre><h2>Response</h2><pre><code></code></pre><pre><code><code>[
  {
    "alertId": "ALT-1001",
    "routerId": "RTR-1001",
    "message": "Packet loss exceeded threshold",
    "severity": "CRITICAL",
    "timestamp": 1710009999
  }
]</code></code></pre><div><hr></div><h1>E. Execute Manual Remediation</h1><pre><code></code></pre><pre><code><code>POST /api/v1/remediation/execute</code></code></pre><h2>Request</h2><pre><code></code></pre><pre><code><code>{
  "routerId": "RTR-1001",
  "action": "restart_bgp"
}</code></code></pre><h2>Response</h2><pre><code></code></pre><pre><code><code>{
  "executionId": "REM-1009",
  "status": "IN_PROGRESS"
}</code></code></pre><div><hr></div><h1>7. Database Design</h1><div><hr></div><h1>A. Router Metadata Table</h1><pre><code></code></pre><pre><code><code>CREATE TABLE routers (
    router_id VARCHAR(50) PRIMARY KEY,
    hostname VARCHAR(255),
    ip_address VARCHAR(50),
    vendor VARCHAR(50),
    model VARCHAR(50),
    location VARCHAR(255),
    status VARCHAR(20),
    created_at TIMESTAMP
);</code></code></pre><div><hr></div><h1>B. Telemetry Table (Time-Series DB)</h1><pre><code></code></pre><pre><code><code>CREATE TABLE telemetry_metrics (
    router_id VARCHAR(50),
    metric_name VARCHAR(50),
    metric_value DOUBLE,
    ts TIMESTAMP,
    PRIMARY KEY(router_id, ts, metric_name)
);</code></code></pre><p>Recommended DB:</p><ul><li><p>InfluxDB<br></p></li><li><p>OpenTSDB<br></p></li></ul><div><hr></div><h1>C. Alert Table</h1><pre><code></code></pre><pre><code><code>CREATE TABLE alerts (
    alert_id VARCHAR(50) PRIMARY KEY,
    router_id VARCHAR(50),
    severity VARCHAR(20),
    message TEXT,
    status VARCHAR(20),
    created_at TIMESTAMP
);</code></code></pre><div><hr></div><h1>D. Policy Table</h1><pre><code></code></pre><pre><code><code>CREATE TABLE remediation_policies (
    policy_id VARCHAR(50) PRIMARY KEY,
    policy_name VARCHAR(255),
    condition_expression TEXT,
    action VARCHAR(100),
    severity VARCHAR(20),
    enabled BOOLEAN
);</code></code></pre><div><hr></div><h1>E. Remediation Execution Table</h1><pre><code></code></pre><pre><code><code>CREATE TABLE remediation_execution (
    execution_id VARCHAR(50) PRIMARY KEY,
    router_id VARCHAR(50),
    action VARCHAR(100),
    status VARCHAR(50),
    started_at TIMESTAMP,
    completed_at TIMESTAMP,
    rollback_status VARCHAR(50)
);</code></code></pre><div><hr></div><h1>8. Storage Choices</h1><div class="highlighted_code_block" data-attrs="{&quot;language&quot;:&quot;plaintext&quot;,&quot;nodeId&quot;:&quot;7e32a657-9bc2-4e30-aaa7-0a7885a64fbd&quot;}" data-component-name="HighlightedCodeBlockToDOM"><pre class="shiki"><code class="language-plaintext">| Data Type         | Database             |
| ----------------- | -------------------- |
| Router Metadata   | PostgreSQL           |
| Telemetry Metrics | InfluxDB / Cassandra |
| Logs              | Elasticsearch        |
| Alerts            | PostgreSQL           |
| Event Streaming   | Kafka                |
| ML Features       | S3/HDFS              |
</code></pre></div><div><hr></div><h1>9. Microservices</h1><div class="highlighted_code_block" data-attrs="{&quot;language&quot;:&quot;plaintext&quot;,&quot;nodeId&quot;:&quot;4322dce3-faa2-40ab-9a0e-939f39dffb83&quot;}" data-component-name="HighlightedCodeBlockToDOM"><pre class="shiki"><code class="language-plaintext">| Service                     | Responsibility                |
| --------------------------- | ----------------------------- |
| API Gateway                 | Authentication, routing       |
| Device Service              | Router metadata management    |
| Telemetry Ingestion Service | Accept telemetry              |
| Detection Engine            | Fault detection               |
| Policy Engine               | Evaluate remediation policies |
| Remediation Service         | Execute preventive actions    |
| Alert Service               | Notifications                 |
| Analytics Service           | Dashboards and trends         |
| ML Prediction Service       | Predict future failures       |
</code></pre></div><div><hr></div><h1>10. Microservices Interaction Flow</h1><h2>Scenario:</h2><p>CPU spike detected on router.</p><pre><code></code></pre><pre><code><code>1. Router sends telemetry
2. Collector publishes to Kafka
3. Detection Engine consumes telemetry
4. Rule matched: CPU &gt; 90%
5. Alert generated
6. Policy Engine checks remediation rules
7. Remediation Service restarts interface
8. Result published back to Kafka
9. Alert Service sends PagerDuty alert
10. Analytics Service updates dashboard</code></code></pre><div><hr></div><h1>11. Sequence Flow Diagram</h1><pre><code></code></pre><pre><code><code>Router
   |
   | Telemetry
   v
Collector Service
   |
   | Publish Event
   v
Kafka
   |
   | Consume
   v
Detection Engine
   |
   | Fault Detected
   v
Policy Engine
   |
   | Execute Action
   v
Remediation Service
   |
   | SSH/NETCONF
   v
Router

Detection Engine
   |
   | Create Alert
   v
Alert Service
   |
   | Notify
   v
PagerDuty / Slack / Email</code></code></pre><div><hr></div><h1>12. Scaling Strategy</h1><h2>Horizontal Scaling</h2><ul><li><p>Multiple collectors<br></p></li><li><p>Partitioned Kafka topics<br></p></li><li><p>Stateless detection workers<br></p></li></ul><div><hr></div><h2>Kafka Partitioning</h2><p>Partition by:</p><pre><code></code></pre><pre><code><code>hash(routerId)</code></code></pre><p>Ensures:</p><ul><li><p>Ordering per router<br></p></li><li><p>Balanced processing<br></p></li></ul><div><hr></div><h2>Telemetry Optimization</h2><p>Use:</p><ul><li><p>Compression<br></p></li><li><p>Batch ingestion<br></p></li><li><p>Sampling<br></p></li><li><p>Aggregation windows<br></p></li></ul><div><hr></div><h1>13. Reliability &amp; Fault Tolerance</h1><h2>Retry Mechanisms</h2><ul><li><p>Exponential backoff<br></p></li><li><p>Dead-letter queues<br></p></li></ul><div><hr></div><h2>Exactly Once Processing</h2><p>Use:</p><ul><li><p>Kafka transactions<br></p></li><li><p>Idempotent consumers<br></p></li></ul><div><hr></div><h2>Multi-Region Deployment</h2><p>Deploy:</p><ul><li><p>Active-active clusters<br></p></li><li><p>Geo-replication<br></p></li></ul><div><hr></div><h1>14. Security Considerations</h1><ul><li><p>mTLS between routers and collectors<br></p></li><li><p>RBAC for remediation APIs<br></p></li><li><p>Encrypted telemetry<br></p></li><li><p>Audit logs for all actions<br></p></li><li><p>Secret management using:<br></p><ul><li><p>HashiCorp Vault<br></p></li></ul></li></ul><div><hr></div><h1>15. Bottlenecks &amp; Optimizations</h1><div class="highlighted_code_block" data-attrs="{&quot;language&quot;:&quot;plaintext&quot;,&quot;nodeId&quot;:&quot;892f76d3-e4fe-468e-8ab1-6fa214ec26aa&quot;}" data-component-name="HighlightedCodeBlockToDOM"><pre class="shiki"><code class="language-plaintext">| Bottleneck            | Optimization        |
| --------------------- | ------------------- |
| High telemetry volume | Kafka batching      |
| Detection lag         | Stream processing   |
| Alert storms          | Alert deduplication |
| Expensive queries     | Pre-aggregation     |
| Large storage         | Tiered retention    |
</code></pre></div><div><hr></div><h1>16. Interview Deep Dive Questions</h1><ol><li><p>How will you detect interface flapping efficiently?<br></p></li><li><p>Why choose Kafka over RabbitMQ?<br></p></li><li><p>How would you avoid alert storms?<br></p></li><li><p>How will rollback work during failed remediation?<br></p></li><li><p>How do you guarantee ordering per router?<br></p></li><li><p>How would ML-based prediction integrate?<br></p></li><li><p>How would the system behave during Kafka outages?<br></p></li><li><p>How do you prevent false positives?<br></p></li><li><p>How would you support millions of routers?<br></p></li><li><p>How would you design multi-region failover?<br></p></li></ol><p></p>]]></content:encoded></item><item><title><![CDATA[Why Your Java Counter Prints Less Than 200000 , A Deep Dive into Race Conditions]]></title><description><![CDATA[Modern backend systems process millions of concurrent operations every second.]]></description><link>https://programmingappliedai.substack.com/p/why-your-java-counter-prints-less</link><guid isPermaLink="false">https://programmingappliedai.substack.com/p/why-your-java-counter-prints-less</guid><dc:creator><![CDATA[Shashank Mishra]]></dc:creator><pubDate>Tue, 12 May 2026 16:15:26 GMT</pubDate><enclosure url="iframe.php?url=https%3A%2F%2Fsubstackcdn.com%2Fimage%2Ffetch%2F%24s_%21riGX%21%2Cw_256%2Cc_limit%2Cf_auto%2Cq_auto%3Agood%2Cfl_progressive%3Asteep%2Fhttps%253A%252F%252Fsubstack-post-media.s3.amazonaws.com%252Fpublic%252Fimages%252F58e132e8-cd28-4037-b0ef-feabb2b68221_144x144.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Modern backend systems process millions of concurrent operations every second.<br>Yet, one of the simplest Java programs can expose one of the most important concepts in concurrent programming: <strong>Race Conditions</strong>.</p><p>Consider this code:</p><pre><code></code></pre><pre><code><code>class Counter {
    int count = 0;

    void increment() {
        count++;
    }
}

public class Test {
    public static void main(String[] args) throws Exception {
        Counter counter = new Counter();

        Thread t1 = new Thread(() -&gt; {
            for (int i = 0; i &lt; 100000; i++) {
                counter.increment();
            }
        });

        Thread t2 = new Thread(() -&gt; {
            for (int i = 0; i &lt; 100000; i++) {
                counter.increment();
            }
        });

        t1.start();
        t2.start();

        t1.join();
        t2.join();

        System.out.println(counter.count);
    }
}</code></code></pre><p>At first glance, the answer should obviously be:</p><pre><code></code></pre><pre><code><code>200000</code></code></pre><p>Two threads.<br><br>Each increments <code>100000</code> times.</p><p>So why does the output often become:</p><pre><code></code></pre><pre><code><code>173421
189302
196774</code></code></pre><p>and almost never exactly <code>200000</code>?</p><p>Let&#8217;s break it down.</p><div><hr></div><h1>The Real Problem: <code>count++</code> Is NOT Atomic</h1><p>Most developers assume:</p><pre><code></code></pre><pre><code><code>count++;</code></code></pre><p>is a single operation.</p><p>It is not.</p><p>Under the hood, it becomes <strong>three separate CPU operations</strong>:</p><pre><code></code></pre><pre><code><code>1. Read count from memory
2. Increment locally
3. Write updated value back</code></code></pre><p>Equivalent pseudo-operations:</p><pre><code></code></pre><pre><code><code>temp = count;
temp = temp + 1;
count = temp;</code></code></pre><p>Now imagine two threads executing simultaneously.</p><div><hr></div><h1>The Race Condition</h1><p>Suppose:</p><pre><code></code></pre><pre><code><code>count = 5</code></code></pre><p>Now both threads execute <code>count++</code>.</p><div><hr></div><h2>Thread Interleaving</h2><p>StepThread 1Thread 2count1Read 552Read 553Increment to 654Increment to 655Write 666Write 66</p><p>Expected result:</p><pre><code></code></pre><pre><code><code>7</code></code></pre><p>Actual result:</p><pre><code></code></pre><pre><code><code>6</code></code></pre><p>One increment is lost.</p><p>This is called a:</p><h1>&#9888;&#65039; Lost Update Problem</h1><p>And because this happens thousands of times across both threads, the final result becomes unpredictable.</p><div><hr></div><h1>Why Does This Happen?</h1><p>Because:</p><ul><li><p>Threads share the same heap memory<br></p></li><li><p>CPU scheduling is nondeterministic<br></p></li><li><p>Context switching can occur anytime<br></p></li><li><p><code>count++</code> is not thread-safe<br></p></li></ul><p>This entire category of bugs falls under:</p><h1>&#9888;&#65039; Race Conditions</h1><p>A race condition occurs when:</p><blockquote><p>Multiple threads access and modify shared state concurrently without proper synchronization.</p></blockquote><div><hr></div><h1>How to Fix It</h1><p>There are multiple ways.</p><p>Each has different performance and scalability tradeoffs.</p><div><hr></div><h1>1. Using <code>synchronized</code></h1><pre><code></code></pre><pre><code><code>class Counter {
    int count = 0;

    synchronized void increment() {
        count++;
    }
}</code></code></pre><p>Now only one thread can execute <code>increment()</code> at a time.</p><div><hr></div><h2>How It Works</h2><p>Java uses an intrinsic monitor lock.</p><p>Before entering:</p><pre><code></code></pre><pre><code><code>increment()</code></code></pre><p>thread acquires the monitor.</p><p>Other threads wait.</p><div><hr></div><h2>Pros</h2><p>&#10004; Easy to understand<br><br>&#10004; Guarantees correctness<br><br>&#10004; Built into JVM</p><div><hr></div><h2>Cons</h2><p>&#10060; Blocking<br><br>&#10060; Context switching overhead<br><br>&#10060; Poor scalability under heavy contention</p><div><hr></div><h1>2. Using <code>ReentrantLock</code></h1><pre><code></code></pre><pre><code><code>import java.util.concurrent.locks.ReentrantLock;

class Counter {
    int count = 0;

    ReentrantLock lock = new ReentrantLock();

    void increment() {
        lock.lock();

        try {
            count++;
        } finally {
            lock.unlock();
        }
    }
}</code></code></pre><div><hr></div><h2>Why Use It?</h2><p>More flexible than <code>synchronized</code>.</p><p>Supports:</p><ul><li><p>Fair locking<br></p></li><li><p>Try lock<br></p></li><li><p>Interruptible lock acquisition<br></p></li><li><p>Timed waits<br></p></li></ul><div><hr></div><h2>Pros</h2><p>&#10004; More control<br><br>&#10004; Better advanced concurrency handling</p><div><hr></div><h2>Cons</h2><p>&#10060; Manual unlock required<br><br>&#10060; Still blocking</p><div><hr></div><h1>3. Using <code>AtomicInteger</code> (Best for Counters)</h1><pre><code></code></pre><pre><code><code>import java.util.concurrent.atomic.AtomicInteger;

class Counter {
    AtomicInteger count = new AtomicInteger();

    void increment() {
        count.incrementAndGet();
    }
}</code></code></pre><div><hr></div><h1>Why This Is Better</h1><p><code>AtomicInteger</code> uses:</p><h1>&#9889; Compare-And-Swap (CAS)</h1><p>instead of locking.</p><div><hr></div><h1>What CAS Does</h1><p>CPU instruction:</p><pre><code></code></pre><pre><code><code>if current_value == expected_value
    update
else
    retry</code></code></pre><p>No thread blocking.</p><p>No monitor locking.</p><p>Extremely efficient.</p><div><hr></div><h1>Internally</h1><pre><code></code></pre><pre><code><code>while(true) {
   int existing = value;
   int next = existing + 1;

   if(CAS(existing, next))
       break;
}</code></code></pre><div><hr></div><h1>Why Modern Systems Prefer Atomic Operations</h1><p>High-performance systems like:</p><ul><li><p>Kafka<br></p></li><li><p>Netty<br></p></li><li><p>Aerospike<br></p></li><li><p>Cassandra<br></p></li><li><p>Redis internals<br></p></li></ul><p>heavily rely on:</p><ul><li><p>Lock-free algorithms<br></p></li><li><p>CAS operations<br></p></li><li><p>Atomic primitives<br></p></li></ul><p>because locks become bottlenecks at scale.</p><div><hr></div><h1>Performance Comparison</h1><p>ApproachThread SafeBlockingScalablePlain int&#10060;&#10060;&#10060;synchronized&#9989;&#9989;MediumReentrantLock&#9989;&#9989;MediumAtomicInteger&#9989;&#10060;High</p><div><hr></div><h1>But AtomicInteger Is Not Always Enough</h1><p>For extremely high contention systems:</p><pre><code></code></pre><pre><code><code>100+ threads
millions of increments/sec</code></code></pre><p>even CAS retries become expensive.</p><p>That&#8217;s why Java introduced:</p><h1>&#9889; LongAdder</h1><p>Used internally in:</p><ul><li><p>ConcurrentHashMap<br></p></li><li><p>Metrics systems<br></p></li><li><p>High throughput counters<br></p></li></ul><p>It reduces contention using striped counters.</p><div><hr></div><h1>Real-World Backend Engineering Insight</h1><p>This tiny example explains why distributed systems are hard.</p><p>Now imagine:</p><ul><li><p>Millions of concurrent users<br></p></li><li><p>Multiple JVMs<br></p></li><li><p>Distributed databases<br></p></li><li><p>Replication<br></p></li><li><p>Network retries<br></p></li></ul><p>The exact same &#8220;lost update&#8221; problem appears everywhere:</p><ul><li><p>Inventory systems<br></p></li><li><p>Banking transactions<br></p></li><li><p>Payment systems<br></p></li><li><p>Distributed counters<br></p></li><li><p>Leaderboards<br></p></li></ul><p>Concurrency bugs scale from a single integer &#8594; to entire distributed architectures.</p><div><hr></div><h1>Final Takeaway</h1><p>The biggest lesson is:</p><blockquote><p>Concurrency problems are rarely visible in code syntax.</p></blockquote><p>The bug is hidden inside:</p><pre><code></code></pre><pre><code><code>count++;</code></code></pre><p>What looks like one operation is actually multiple CPU-level operations racing against each other.</p><p>Understanding this deeply is foundational for:</p><ul><li><p>Multithreading<br></p></li><li><p>JVM internals<br></p></li><li><p>High-performance backend engineering<br></p></li><li><p>Distributed systems design<br></p></li></ul><p>Because at scale:</p><blockquote><p>Correctness is harder than performance.</p></blockquote><p>#Java #Concurrency #Multithreading #BackendEngineering #DistributedSystems #JVM #SystemDesign</p>]]></content:encoded></item><item><title><![CDATA[HLD:Podcast Tracking Service(Asked in Confluent)]]></title><description><![CDATA[If you&#8217;re looking for paid 1:1 mentorship with a strong focus on LLD (core emphasis on Multithreading), HLD, DSA, and system design research papers, feel free to reach out.]]></description><link>https://programmingappliedai.substack.com/p/hldpodcast-tracking-serviceasked</link><guid isPermaLink="false">https://programmingappliedai.substack.com/p/hldpodcast-tracking-serviceasked</guid><dc:creator><![CDATA[Shashank Mishra]]></dc:creator><pubDate>Fri, 01 May 2026 06:06:50 GMT</pubDate><enclosure url="iframe.php?url=https%3A%2F%2Fsubstackcdn.com%2Fimage%2Ffetch%2F%24s_%21riGX%21%2Cw_256%2Cc_limit%2Cf_auto%2Cq_auto%3Agood%2Cfl_progressive%3Asteep%2Fhttps%253A%252F%252Fsubstack-post-media.s3.amazonaws.com%252Fpublic%252Fimages%252F58e132e8-cd28-4037-b0ef-feabb2b68221_144x144.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h3><strong>If you&#8217;re looking for paid 1:1 mentorship with a strong focus on LLD (core emphasis on Multithreading), HLD, DSA, and system design research papers, feel free to reach out.</strong></h3><p>&#128233; <strong>Contact:</strong> programmingappliedai@gmail.com</p><p></p><h1>1. Problem Framing</h1><p>Design a <strong>Podcast Tracking Service</strong> where users can:</p><ul><li><p>Follow podcasts</p></li><li><p>Track listening progress</p></li><li><p>Get updates on new episodes</p></li><li><p>Resume playback across devices</p></li></ul><div><hr></div><h1>&#9989; 2. Functional Requirements (FR)</h1><ol><li><p>User can <strong>search &amp; discover podcasts</strong></p></li><li><p>User can <strong>follow / unfollow podcasts</strong></p></li><li><p>User can <strong>view episodes of a podcast</strong></p></li><li><p>User can <strong>mark episode as played / in-progress</strong></p></li><li><p>Track <strong>listening progress (timestamp-based)</strong></p></li><li><p>Resume playback from last position</p></li><li><p>Notify users on <strong>new episode release</strong></p></li><li><p>Show <strong>user feed (new episodes from followed podcasts)</strong></p></li><li><p>Support <strong>multi-device sync</strong></p></li><li><p>Maintain <strong>listening history</strong></p></li></ol><div><hr></div><h1>&#9881;&#65039; 3. Non-Functional Requirements (NFR)</h1><ol><li><p><strong>High write throughput</strong> (progress updates are frequent)</p></li><li><p><strong>Low latency reads</strong> (resume playback must be instant)</p></li><li><p><strong>High availability</strong> (user data must not be lost)</p></li><li><p><strong>Scalability</strong> (millions of users, podcasts)</p></li><li><p><strong>Eventual consistency acceptable</strong> (for feeds/notifications)</p></li><li><p><strong>Durability of progress tracking</strong></p></li><li><p><strong>Idempotent APIs</strong> (progress updates retry-safe)</p></li></ol><div><hr></div><h1>&#129521; 4. Core Entities</h1><h3>Key Entities:</h3><ul><li><p><strong>User</strong></p></li><li><p><strong>Podcast</strong></p></li><li><p><strong>Episode</strong></p></li><li><p><strong>UserSubscription</strong></p></li><li><p><strong>ListeningProgress</strong></p></li><li><p><strong>ListeningHistory</strong></p></li></ul><div><hr></div><h1>&#128452;&#65039; 5. Database Design</h1><h3>&#128313; 1. User</h3><pre><code>user_id (PK)
name
email
created_at</code></pre><div><hr></div><h3>&#128313; 2. Podcast</h3><pre><code>podcast_id (PK)
title
description
publisher
category
created_at</code></pre><div><hr></div><h3>&#128313; 3. Episode</h3><pre><code>episode_id (PK)
podcast_id (FK)
title
duration
publish_time
audio_url</code></pre><div><hr></div><h3>&#128313; 4. UserSubscription</h3><pre><code>user_id (PK, FK)
podcast_id (PK, FK)
subscribed_at</code></pre><p>&#128073; Composite PK for fast lookup</p><div><hr></div><h3>&#128313; 5. ListeningProgress (HOT PATH)</h3><pre><code>user_id (PK)
episode_id (PK)
progress_seconds
last_updated
status (IN_PROGRESS / COMPLETED)</code></pre><p>&#128073; Stored in <strong>NoSQL (Cassandra/DynamoDB)</strong><br><br>Reason: high write frequency</p><div><hr></div><h3>&#128313; 6. ListeningHistory</h3><pre><code>user_id
episode_id
completed_at</code></pre><p>&#128073; Append-only &#8594; good for analytics</p><div><hr></div><h1>&#128451;&#65039; 6. Database Choices</h1><div class="highlighted_code_block" data-attrs="{&quot;language&quot;:&quot;plaintext&quot;,&quot;nodeId&quot;:&quot;132fb13b-7953-4b87-ab62-b1e8217e38ec&quot;}" data-component-name="HighlightedCodeBlockToDOM"><pre class="shiki"><code class="language-plaintext">| Use Case               | DB                            |
| ---------------------- | ----------------------------- |
| User, Podcast metadata | MySQL / PostgreSQL            |
| Episodes               | MySQL (or Elastic for search) |
| Listening Progress     | Cassandra / DynamoDB          |
| Feed / Notifications   | Redis + Kafka                 |
| Search                 | Elasticsearch                 |
</code></pre></div><div><hr></div><h1>&#128268; 7. API Design</h1><h3>&#128313; 1. Follow Podcast</h3><pre><code>POST /users/{userId}/follow

Request:
{
  &#8220;podcastId&#8221;: &#8220;p123&#8221;
}</code></pre><div><hr></div><h3>&#128313; 2. Get User Subscriptions</h3><pre><code>GET /users/{userId}/subscriptions</code></pre><div><hr></div><h3>&#128313; 3. Get Episodes of Podcast</h3><pre><code>GET /podcasts/{podcastId}/episodes</code></pre><div><hr></div><h3>&#128313; 4. Update Listening Progress (CRITICAL API)</h3><pre><code>POST /progress

Request:
{
  &#8220;userId&#8221;: &#8220;u1&#8221;,
  &#8220;episodeId&#8221;: &#8220;e1&#8221;,
  &#8220;progressSeconds&#8221;: 120
}</code></pre><p>&#128073; Must be:</p><ul><li><p>Idempotent<br></p></li><li><p>High throughput<br></p></li></ul><div><hr></div><h3>&#128313; 5. Get Resume Playback</h3><pre><code>GET /progress?userId=u1&amp;episodeId=e1</code></pre><div><hr></div><h3>&#128313; 6. Get User Feed</h3><pre><code>GET /users/{userId}/feed</code></pre><div><hr></div><h1>&#129513; 8. High-Level Architecture</h1><pre><code>                &#9484;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9488;
                &#9474; API Gateway  &#9474;
                &#9492;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9516;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9496;
                       &#9474;
        &#9484;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9532;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9488;
        &#9474;              &#9474;              &#9474;
 User Service   Podcast Service   Progress Service
        &#9474;              &#9474;              &#9474;
        &#9474;              &#9474;              &#9474;
   MySQL DB       MySQL DB       Cassandra
                                      &#9474;
                                  Kafka
                                      &#9474;
                              Notification Service
                                      &#9474;
                                   Redis</code></pre><div><hr></div><h1>&#128260; 9. Microservices Breakdown</h1><h3>&#128313; 1. User Service</h3><ul><li><p>Manage users<br></p></li><li><p>Auth (optional)<br></p></li></ul><div><hr></div><h3>&#128313; 2. Podcast Service</h3><ul><li><p>Podcast metadata<br></p></li><li><p>Episode management<br></p></li></ul><div><hr></div><h3>&#128313; 3. Subscription Service</h3><ul><li><p>Follow/unfollow<br></p></li><li><p>Stores mapping<br></p></li></ul><div><hr></div><h3>&#128313; 4. Progress Service (HOT SERVICE)</h3><ul><li><p>Handles frequent writes<br></p></li><li><p>Writes to Cassandra<br></p></li><li><p>Publishes events to Kafka<br></p></li></ul><div><hr></div><h3>&#128313; 5. Feed Service</h3><ul><li><p>Aggregates new episodes<br></p></li><li><p>Pull vs Push model<br></p></li></ul><div><hr></div><h3>&#128313; 6. Notification Service</h3><ul><li><p>Consumes Kafka events<br></p></li><li><p>Sends push/email notifications<br></p></li></ul><div><hr></div><h1>&#128257; 10. Flow: Update Listening Progress</h1><pre><code>Client &#8594; API Gateway &#8594; Progress Service
        &#8594; Write to Cassandra
        &#8594; Publish event to Kafka
                &#8595;
        Notification / Analytics consumers</code></pre><div><hr></div><h1>&#128257; 11. Flow: New Episode Release</h1><pre><code>Podcast Service
    &#8594; Publish &#8220;New Episode Event&#8221; to Kafka
            &#8595;
    Feed Service
        &#8594; Fan-out to followers (push model)
            &#8595;
    Notification Service</code></pre><div><hr></div><h1>&#9878;&#65039; 12. Key Design Decisions</h1><h3>&#128313; Why Cassandra for Progress?</h3><ul><li><p>High write throughput<br></p></li><li><p>Partition key = user_id &#8594; efficient<br></p></li></ul><div><hr></div><h3>&#128313; Push vs Pull Feed</h3><p>ApproachTradeoffPullSimple but slowPushFast reads, heavy writes</p><p>&#128073; Use <strong>hybrid model</strong></p><div><hr></div><h3>&#128313; Idempotency for Progress API</h3><ul><li><p>Use <code>(user_id, episode_id)</code> as key<br></p></li><li><p>Always overwrite latest progress<br></p></li></ul><div><hr></div><h1>&#128279; 13. Decoupling Strategy (Important for Interview)</h1><ol><li><p>Use <strong>Kafka for async communication</strong><br></p></li><li><p>Services don&#8217;t call each other directly<br></p></li><li><p>Event-driven architecture:<br></p><ul><li><p>Progress updates &#8594; analytics<br></p></li><li><p>New episodes &#8594; feed generation<br></p></li></ul></li></ol><div><hr></div><h1>&#128640; 14. Scaling Considerations</h1><ul><li><p>Partition Cassandra by <code>user_id</code><br></p></li><li><p>Cache feed in Redis<br></p></li><li><p>Use CDN for audio files<br></p></li><li><p>Batch updates for analytics<br></p></li></ul><div><hr></div><h1>&#129504; 15. Follow-Up Questions (They Might Ask)</h1><h3>&#10067; How to handle rewind/skip edge cases?</h3><p>&#8594; Always store latest timestamp</p><h3>&#10067; What if user listens offline?</h3><p>&#8594; Sync on reconnect (client-side buffering)</p><h3>&#10067; How to avoid write overload?</h3><p>&#8594; Throttle updates (every 5&#8211;10 sec instead of every second)</p><h3>&#10067; Multi-device consistency?</h3><p>&#8594; Last write wins (timestamp-based conflict resolution)</p><div><hr></div><p></p><ul><li><p>Deep dive on <strong>Kafka topic design &amp; partitioning</strong><br></p></li><li><p><strong>Cassandra schema optimization (LSM trees, compaction)</strong><br></p></li><li><p>Or <strong>Feed system design (fan-out on write vs read)</strong></p><p><br></p></li></ul><h1>1. Kafka Design (Topics, Partitions, Throughput)</h1><p>You&#8217;re using Kafka as the backbone for decoupling, so design it intentionally&#8212;not vaguely.</p><div><hr></div><h2>&#129525; Key Events</h2><h3>1. Progress Updates</h3><pre><code>topic: listening-progress-events</code></pre><p>Event:</p><pre><code>{
  userId,
  episodeId,
  progressSeconds,
  timestamp
}</code></pre><div><hr></div><h3>2. New Episode Release</h3><pre><code>topic: new-episode-events</code></pre><p>Event:</p><pre><code>{
  podcastId,
  episodeId,
  publishTime
}</code></pre><div><hr></div><h2>&#9881;&#65039; Partitioning Strategy</h2><h3>&#128313; Progress Events</h3><p>&#128073; Partition by <code>userId</code></p><p><strong>Why?</strong></p><ul><li><p>Guarantees ordering per user<br></p></li><li><p>Avoids race conditions in progress updates<br></p></li></ul><div><hr></div><h3>&#128313; New Episode Events</h3><p>&#128073; Partition by <code>podcastId</code></p><p><strong>Why?</strong></p><ul><li><p>All followers of a podcast handled consistently<br></p></li><li><p>Enables batching for fan-out<br></p></li></ul><div><hr></div><h2>&#128202; Throughput Estimation (Back-of-envelope)</h2><p>Let&#8217;s assume:</p><ul><li><p>10M daily active users<br></p></li><li><p>Each sends progress every 10 sec<br></p></li></ul><p>&#128073; Writes/sec:</p><pre><code>10M * (1 update / 10 sec) = 1M events/sec</code></pre><p>&#128073; You <strong>must</strong>:</p><ul><li><p>Use multiple partitions (1000+)<br></p></li><li><p>Use batching producers<br></p></li><li><p>Enable compression<br></p></li></ul><div><hr></div><h2>&#9888;&#65039; Common Mistake</h2><p>Don&#8217;t do:</p><ul><li><p>One partition &#8594; bottleneck<br></p></li><li><p>Random partition &#8594; breaks ordering<br></p></li></ul><div><hr></div><h1>&#129521; 2. Cassandra Schema Deep Dive</h1><p>This is where most answers stay shallow&#8212;you shouldn&#8217;t.</p><div><hr></div><h2>&#128313; Table: Listening Progress</h2><pre><code>PRIMARY KEY ((user_id), episode_id)</code></pre><p>&#128073; Partition key: <code>user_id</code><br><br>&#128073; Clustering key: <code>episode_id</code></p><div><hr></div><h2>&#10071; Problem</h2><p>What if a user listens to <strong>1000+ episodes</strong>?</p><p>&#8594; Partition becomes large</p><div><hr></div><h2>&#9989; Better Design</h2><h3>Option 1: Bucketing</h3><pre><code>PRIMARY KEY ((user_id, bucket), episode_id)</code></pre><p>Where:</p><pre><code>bucket = hash(episode_id) % N</code></pre><p>&#128073; Prevents hot partitions</p><div><hr></div><h3>Option 2: Time-based Bucketing (better for history)</h3><pre><code>PRIMARY KEY ((user_id, month), episode_id)</code></pre><div><hr></div><h2>&#128313; Write Pattern</h2><ul><li><p>Always <strong>upsert</strong><br></p></li><li><p>Last write wins<br></p></li></ul><div><hr></div><h2>&#128313; Read Pattern</h2><ul><li><p>Fetch by <code>(user_id, episode_id)</code> &#8594; fast O(1)<br></p></li></ul><div><hr></div><h2>&#9888;&#65039; Compaction Strategy</h2><p>Use:</p><ul><li><p><strong>Leveled Compaction</strong> &#8594; for read-heavy<br></p></li><li><p><strong>Size-Tiered</strong> &#8594; for write-heavy (better here)<br></p></li></ul><div><hr></div><h1>&#9889; 3. Feed System Design (THE differentiator)</h1><p>This is where interviewers test depth.</p><div><hr></div><h2>&#129513; Problem</h2><p>User follows 100 podcasts.<br><br>Each podcast releases episodes.</p><p>&#128073; How do you build the <strong>user feed</strong>?</p><div><hr></div><h1>&#127386; Approach 1: Fan-out on Read</h1><h3>Flow:</h3><pre><code>User opens app &#8594;
Fetch all followed podcasts &#8594;
Fetch latest episodes &#8594;
Merge + sort</code></pre><div><hr></div><h3>&#10060; Problem:</h3><ul><li><p>Slow<br></p></li><li><p>High read amplification<br></p></li></ul><div><hr></div><h1>&#127386; Approach 2: Fan-out on Write</h1><h3>Flow:</h3><pre><code>New Episode &#8594;
Push to all followers&#8217; feeds</code></pre><div><hr></div><h3>&#10060; Problem:</h3><ul><li><p>If podcast has 10M followers &#8594; explosion<br></p></li></ul><div><hr></div><h1>&#9989; Hybrid Approach (Best Answer)</h1><h3>Strategy:</h3><ul><li><p>Small podcasts &#8594; fan-out on write<br></p></li><li><p>Large podcasts &#8594; fan-out on read<br></p></li></ul><div><hr></div><h2>&#128313; Feed Table (Redis / Cassandra)</h2><pre><code>user_id &#8594; list of episode_ids (sorted by time)</code></pre><div><hr></div><h2>&#128260; Flow: New Episode</h2><pre><code>Podcast Service
    &#8594; Kafka (new-episode-events)
        &#8595;
Feed Service
    &#8594; Fetch followers
    &#8594; If small &#8594; push to feed
    &#8594; If large &#8594; mark for pull</code></pre><div><hr></div><h2>&#9889; Optimization</h2><ul><li><p>Use <strong>Redis Sorted Sets</strong><br></p></li><li><p>Score = timestamp<br></p></li></ul><div><hr></div><h1>&#128257; 4. End-to-End Flow (Putting It All Together)</h1><div><hr></div><h2>&#127911; Flow: User Listening</h2><pre><code>Client
 &#8594; API Gateway
 &#8594; Progress Service
 &#8594; Cassandra (write)
 &#8594; Kafka (event)

Kafka Consumers:
 &#8594; Analytics Service
 &#8594; Recommendation Service</code></pre><div><hr></div><h2>&#127381; Flow: New Episode</h2><pre><code>Podcast Service
 &#8594; Kafka

Feed Service
 &#8594; Fan-out (hybrid)

Notification Service
 &#8594; Push alerts</code></pre><div><hr></div><h1>&#128279; 5. Decoupling Strategy (Strong Signal)</h1><div><hr></div><h2>&#10060; Bad Design</h2><pre><code>Progress Service &#8594; directly calls Feed Service</code></pre><p>&#128073; Tight coupling</p><div><hr></div><h2>&#9989; Good Design</h2><pre><code>Progress Service &#8594; Kafka &#8594; Consumers</code></pre><p>&#128073; Loose coupling<br><br>&#128073; Scalable<br><br>&#128073; Replayable events</p><div><hr></div><h1>&#129504; 6. Advanced Follow-ups (Be Ready)</h1><div><hr></div><h2>&#10067; How do you handle duplicate Kafka events?</h2><p>&#128073; Use:</p><ul><li><p>Idempotent consumers<br></p></li><li><p>Dedup key = <code>(userId, episodeId, timestamp)</code><br></p></li></ul><div><hr></div><h2>&#10067; How do you handle out-of-order updates?</h2><p>&#128073; Use:</p><pre><code>only update if incoming.timestamp &gt; existing.timestamp</code></pre><div><hr></div><h2>&#10067; How do you reduce progress write load?</h2><p>&#128073; Client optimization:</p><ul><li><p>Send updates every 10 sec (not every second)<br></p></li><li><p>Send only if progress changed significantly<br></p></li></ul><div><hr></div><h2>&#10067; How to scale Kafka consumers?</h2><p>&#128073; Increase:</p><ul><li><p>Consumer groups<br></p></li><li><p>Partitions<br></p></li></ul><div><hr></div><h1>&#129504; Final Interview Tip</h1><p>When you explain this, don&#8217;t just describe components&#8212;<strong>justify every decision</strong>:</p><ul><li><p>&#8220;I chose Cassandra because write-heavy workload&#8221;<br></p></li><li><p>&#8220;Kafka ensures decoupling and replayability&#8221;<br></p></li><li><p>&#8220;Hybrid fan-out avoids celebrity problem&#8221;<br></p></li></ul><div><hr></div><p></p>]]></content:encoded></item><item><title><![CDATA[LLD: Implement Unit tail functionality(asked in Confluent)]]></title><description><![CDATA[If you&#8217;re looking for paid 1:1 mentorship with a strong focus on LLD (core emphasis on Multithreading), HLD, DSA, and system design research papers, feel free to reach out.]]></description><link>https://programmingappliedai.substack.com/p/lld-implement-unit-tail-functionalityasked</link><guid isPermaLink="false">https://programmingappliedai.substack.com/p/lld-implement-unit-tail-functionalityasked</guid><dc:creator><![CDATA[Shashank Mishra]]></dc:creator><pubDate>Fri, 01 May 2026 05:51:25 GMT</pubDate><enclosure url="iframe.php?url=https%3A%2F%2Fsubstackcdn.com%2Fimage%2Ffetch%2F%24s_%21riGX%21%2Cw_256%2Cc_limit%2Cf_auto%2Cq_auto%3Agood%2Cfl_progressive%3Asteep%2Fhttps%253A%252F%252Fsubstack-post-media.s3.amazonaws.com%252Fpublic%252Fimages%252F58e132e8-cd28-4037-b0ef-feabb2b68221_144x144.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h3><strong>If you&#8217;re looking for paid 1:1 mentorship with a strong focus on LLD (core emphasis on Multithreading), HLD, DSA, and system design research papers, feel free to reach out.</strong></h3><p>&#128233; <strong>Contact:</strong> programmingappliedai@gmail.com</p><h3>Requirements</h3><ul><li><p>Read <strong>last N lines</strong></p></li><li><p>Should work for <strong>large files (GBs)</strong> &#8594; cannot load entire file</p></li><li><p>Efficient (O(file_size) worst case, but optimized by reverse reading)</p></li><li><p>Handle edge cases:</p><ul><li><p>File smaller than N lines</p></li><li><p>Very long lines</p></li><li><p>Different line endings</p></li></ul></li></ul><div><hr></div><h1>&#127959;&#65039; LLD Design</h1><h2>1. Core Components</h2><h3><code>TailService</code></h3><ul><li><p>Main service to fetch last N lines</p></li></ul><h3><code>FileReaderStrategy</code></h3><ul><li><p>Strategy pattern for reading:</p><ul><li><p>ForwardReader (simple, small files)</p></li><li><p>ReverseReader (optimized for large files)</p></li></ul></li></ul><h3><code>LineBuffer</code></h3><ul><li><p>Maintains last N lines using deque</p></li></ul><div><hr></div><h2>2. Approach Options</h2><h3>&#10060; Naive Approach</h3><ul><li><p>Read entire file &#8594; keep last N lines</p></li><li><p>Not scalable</p></li></ul><h3>&#9989; Optimal Approach (Reverse Read)</h3><ul><li><p>Use <code>RandomAccessFile</code></p></li><li><p>Start from <strong>end of file</strong></p></li><li><p>Move backwards byte by byte</p></li><li><p>Count <code>\n</code></p></li><li><p>Stop after N lines</p></li></ul><div><hr></div><h1>&#9881;&#65039; Java Implementation (Efficient)</h1><pre><code>import java.io.*;
import java.util.*;

public class TailService {

    public List&lt;String&gt; tail(String filePath, int n) throws IOException {
        if (n &lt;= 0) return Collections.emptyList();

        RandomAccessFile file = new RandomAccessFile(filePath, &#8220;r&#8221;);
        long fileLength = file.length();

        List&lt;String&gt; result = new LinkedList&lt;&gt;();
        StringBuilder lineBuilder = new StringBuilder();

        int lineCount = 0;
        long pointer = fileLength - 1;

        while (pointer &gt;= 0 &amp;&amp; lineCount &lt; n) {
            file.seek(pointer);
            char c = (char) file.read();

            if (c == &#8216;\n&#8217;) {
                if (lineBuilder.length() &gt; 0) {
                    result.add(0, lineBuilder.reverse().toString());
                    lineBuilder.setLength(0);
                    lineCount++;
                }
            } else {
                lineBuilder.append(c);
            }

            pointer--;
        }

        // Add last line if file doesn&#8217;t end with newline
        if (lineBuilder.length() &gt; 0 &amp;&amp; lineCount &lt; n) {
            result.add(0, lineBuilder.reverse().toString());
        }

        file.close();
        return result;
    }

    public static void main(String[] args) throws IOException {
        TailService service = new TailService();
        List&lt;String&gt; lines = service.tail(&#8221;test.txt&#8221;, 10);

        for (String line : lines) {
            System.out.println(line);
        }
    }
}</code></pre><div><hr></div><h1>&#128269; Complexity</h1><div class="highlighted_code_block" data-attrs="{&quot;language&quot;:&quot;plaintext&quot;,&quot;nodeId&quot;:&quot;e6834f51-c7ce-4156-947a-ed170dde8b67&quot;}" data-component-name="HighlightedCodeBlockToDOM"><pre class="shiki"><code class="language-plaintext">| Aspect | Complexity              |
| ------ | ----------------------- |
| Time   | O(file_size) worst case |
| Space  | O(N * avg_line_length)  |
</code></pre></div><div><hr></div><h1>&#9889; Improvements (Production Level)</h1><h2>1. Use Buffered Block Reads</h2><p>Instead of reading char-by-char:</p><ul><li><p>Read chunks (e.g., 4KB)<br></p></li><li><p>Traverse buffer backwards<br></p></li></ul><h2>2. Handle Encoding</h2><ul><li><p>Use <code>CharsetDecoder</code> for UTF-8 safety<br></p></li></ul><h2>3. Support Streams (like <code>tail -f</code>)</h2><ul><li><p>Add file watcher (<code>WatchService</code>)<br></p></li><li><p>Continuously read appended lines<br></p></li></ul><h2>4. Memory Optimization</h2><ul><li><p>Use <code>ArrayDeque</code> instead of LinkedList<br></p></li></ul><div><hr></div><h1>&#129521; Cleaner LLD Version</h1><pre><code>interface TailReader {
    List&lt;String&gt; readLastNLines(String filePath, int n) throws IOException;
}</code></pre><h3>Reverse Reader</h3><pre><code>class ReverseTailReader implements TailReader {
    @Override
    public List&lt;String&gt; readLastNLines(String filePath, int n) throws IOException {
        return new TailService().tail(filePath, n);
    }
}</code></pre><h3>Service Layer</h3><pre><code>class TailApplication {
    private final TailReader reader;

    public TailApplication(TailReader reader) {
        this.reader = reader;
    }

    public void execute(String filePath, int n) throws IOException {
        List&lt;String&gt; lines = reader.readLastNLines(filePath, n);
        lines.forEach(System.out::println);
    }
}</code></pre><div><hr></div><h1>&#128161; Follow-ups (Interview Ready)</h1><p>You can extend this design into:</p><h3>1. <code>tail -f</code> (Real-time streaming)</h3><ul><li><p>Use <code>WatchService</code><br></p></li><li><p>Poll file growth<br></p></li><li><p>Maintain pointer<br></p></li></ul><h3>2. Distributed Logs</h3><ul><li><p>Read from S3 / HDFS<br></p></li><li><p>Use range queries<br></p></li></ul><h3>3. API Service</h3><pre><code>GET /tail?file=abc.log&amp;lines=50</code></pre><h3>4. Large-scale Observability System</h3><ul><li><p>Combine with Kafka + log ingestion<br></p></li><li><p>Real-time tail via WebSockets</p><p><br></p></li></ul><div><hr></div><p><a href="iframe.php?url=https%3A%2F%2Fgithub.com%2Fabcmishra%2FTailServiceInUnix">Unix Functionality Github Link</a><br></p>]]></content:encoded></item><item><title><![CDATA[HLD: Design Temporary Email Service]]></title><description><![CDATA[Problem Statement (Refined)]]></description><link>https://programmingappliedai.substack.com/p/hld-design-temporary-email-service</link><guid isPermaLink="false">https://programmingappliedai.substack.com/p/hld-design-temporary-email-service</guid><dc:creator><![CDATA[Shashank Mishra]]></dc:creator><pubDate>Fri, 01 May 2026 05:40:01 GMT</pubDate><enclosure url="iframe.php?url=https%3A%2F%2Fsubstackcdn.com%2Fimage%2Ffetch%2F%24s_%21riGX%21%2Cw_256%2Cc_limit%2Cf_auto%2Cq_auto%3Agood%2Cfl_progressive%3Asteep%2Fhttps%253A%252F%252Fsubstack-post-media.s3.amazonaws.com%252Fpublic%252Fimages%252F58e132e8-cd28-4037-b0ef-feabb2b68221_144x144.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h1>Problem Statement (Refined)</h1><p>Design a <strong>Temporary Email Service</strong> that allows users to:</p><ul><li><p>Generate disposable email addresses</p></li><li><p>Receive emails in a sandboxed inbox</p></li><li><p>Auto-expire emails and addresses after a TTL</p></li><li><p>Avoid spam/abuse</p></li><li><p>Scale to millions of emails per day</p></li></ul><div><hr></div><h1>&#9989; Functional Requirements (FR)</h1><ol><li><p>Users can <strong>generate temporary email addresses</strong></p></li><li><p>System should <strong>receive emails</strong> sent to these addresses</p></li><li><p>Users can <strong>view emails via UI/API</strong></p></li><li><p>Emails and addresses should <strong>expire automatically (TTL-based)</strong></p></li><li><p>Support <strong>multiple emails per temp address</strong></p></li><li><p>Provide <strong>meaningful / human-readable email IDs (not random hashes)</strong></p></li></ol><div><hr></div><h1>&#9881;&#65039; Non-Functional Requirements (NFR)</h1><ol><li><p><strong>High throughput</strong> (millions of incoming emails/day)</p></li><li><p><strong>Low latency</strong> for inbox retrieval (&lt;200ms)</p></li><li><p><strong>Highly scalable</strong> (horizontal scaling)</p></li><li><p><strong>Fault tolerant</strong> (no email loss)</p></li><li><p><strong>Secure sandboxing</strong> (no malware execution)</p></li><li><p><strong>Abuse prevention</strong> (rate limiting, spam filtering)</p></li></ol><div><hr></div><h1>&#129513; Core Design Challenges</h1><h3>1. Email Address Generation (Important &#128293;)</h3><blockquote><p>Cannot just be hashes &#8594; must be meaningful</p></blockquote><h3>Approach:</h3><p>Use structured format:</p><pre><code>&lt;word&gt;-&lt;word&gt;-&lt;random&gt;@tempmail.com</code></pre><p>Examples:</p><ul><li><p><code>blue-tiger-92@tempmail.com</code><br></p></li><li><p><code>swift-lake-431@tempmail.com</code><br></p></li></ul><h3>Why this works:</h3><ul><li><p>Human-readable<br></p></li><li><p>Easier debugging<br></p></li><li><p>Still unique with suffix<br></p></li></ul><h3>Backend Strategy:</h3><ul><li><p>Dictionary-based generator + counter/random suffix<br></p></li><li><p>Maintain <strong>uniqueness via Redis / DB constraint</strong><br></p></li></ul><div><hr></div><h1>&#127959;&#65039; High-Level Architecture</h1><pre><code>                +-------------------+
                |   DNS (MX Record) |
                +--------+----------+
                         |
                         v
                +-------------------+
                | Email Receiving   |
                | Server (SMTP)     |
                +--------+----------+
                         |
                         v
                +-------------------+
                | Email Parser      |
                +--------+----------+
                         |
          +--------------+--------------+
          |                             |
          v                             v
+-------------------+        +----------------------+
| Spam Filter       |        | Attachment Scanner   |
+--------+----------+        +----------+-----------+
         |                              |
         +--------------+---------------+
                        v
                +-------------------+
                | Message Queue     | (Kafka)
                +--------+----------+
                         |
                         v
                +-------------------+
                | Email Storage     |
                +--------+----------+
                         |
         +---------------+---------------+
         |                               |
         v                               v
+-------------------+        +-------------------+
| Metadata DB       |        | Blob Storage      |
| (Cassandra)       |        | (S3 / GCS)        |
+-------------------+        +-------------------+

                +-------------------+
                | Inbox API Service |
                +--------+----------+
                         |
                         v
                +-------------------+
                | Frontend UI       |
                +-------------------+</code></pre><div><hr></div><h1>&#128260; Key Flow</h1><h3>1. Email Creation</h3><ul><li><p>User requests &#8594; Service generates email ID<br></p></li><li><p>Store in DB with TTL<br></p></li></ul><div><hr></div><h3>2. Email Receiving Flow</h3><ol><li><p>SMTP server receives email<br></p></li><li><p>Parses:<br></p><ul><li><p>To address<br></p></li><li><p>Subject<br></p></li><li><p>Body<br></p></li></ul></li><li><p>Push to Kafka<br></p></li><li><p>Consumers:<br></p><ul><li><p>Store metadata &#8594; Cassandra<br></p></li><li><p>Store attachments &#8594; Blob store<br></p></li></ul></li></ol><div><hr></div><h3>3. Inbox Fetch</h3><ul><li><p>Query by email address<br></p></li><li><p>Fetch recent messages (sorted by timestamp)<br></p></li></ul><div><hr></div><h1>&#129521; Data Modeling</h1><h3>Email Address Table</h3><pre><code>email_id (PK)
created_at
expires_at
status (active/expired)</code></pre><div><hr></div><h3>Email Metadata Table (Cassandra)</h3><pre><code>partition_key: email_id
clustering_key: timestamp

Fields:
- message_id
- subject
- sender
- preview
- blob_url
- created_at</code></pre><div><hr></div><h1>&#9203; TTL Strategy</h1><ul><li><p>Use <strong>DB TTL (Cassandra TTL)</strong><br></p></li><li><p>Also maintain <strong>background cleanup job</strong><br></p></li></ul><div><hr></div><h1>&#128640; Scaling Deep Dive</h1><h2>1. Email Ingestion Scaling</h2><ul><li><p>Multiple SMTP servers behind load balancer<br></p></li><li><p>Partition by domain or hash(email)<br></p></li></ul><div><hr></div><h2>2. Kafka Partitioning</h2><ul><li><p>Partition key = email_id<br></p></li><li><p>Ensures ordering per inbox<br></p></li></ul><div><hr></div><h2>3. Storage Scaling</h2><ul><li><p>Cassandra &#8594; write-heavy optimized<br></p></li><li><p>Blob store &#8594; scalable for attachments<br></p></li></ul><div><hr></div><h2>4. Read Scaling</h2><ul><li><p>Cache inbox in Redis<br></p></li><li><p>Recent emails only<br></p></li></ul><div><hr></div><h1>&#128737;&#65039; Security &amp; Sandboxing</h1><h3>Must handle:</h3><ul><li><p>Malicious links<br></p></li><li><p>Attachments<br></p></li><li><p>Scripts<br></p></li></ul><h3>Approach:</h3><ul><li><p>Strip scripts from HTML<br></p></li><li><p>Convert to safe format<br></p></li><li><p>Virus scan attachments<br></p></li><li><p>Disable external image loading<br></p></li></ul><div><hr></div><h1>&#128683; Abuse Prevention</h1><ul><li><p>Rate limit email creation per IP<br></p></li><li><p>Blocklist domains<br></p></li><li><p>CAPTCHA<br></p></li><li><p>Detect bot patterns<br></p></li></ul><div><hr></div><h1>&#128161; Out-of-the-Box Ideas (Strong Interview Signal)</h1><h3>1. Auto Forwarding Rules</h3><ul><li><p>Forward temp email &#8594; real inbox<br></p></li></ul><div><hr></div><h3>2. Disposable API Keys</h3><ul><li><p>Use temp emails in automated testing<br></p></li></ul><div><hr></div><h3>3. Session-based Emails</h3><ul><li><p>Email tied to browser session<br></p></li><li><p>No login needed<br></p></li></ul><div><hr></div><h3>4. Smart Expiry</h3><ul><li><p>Extend TTL if actively used<br></p></li></ul><div><hr></div><h3>5. Email Categorization</h3><ul><li><p>ML model for:<br></p><ul><li><p>Spam<br></p></li><li><p>OTP<br></p></li><li><p>Promotions<br></p></li></ul></li></ul><div><hr></div><h3>6. Domain Pooling</h3><ul><li><p>Multiple domains:</p></li></ul><pre><code>@maildrop.cc
@tempmail.dev</code></pre><ul><li><p>Avoid blacklisting<br></p></li></ul><div><hr></div><h1>&#128293; Bottlenecks &amp; Tradeoffs</h1><p>ProblemSolutionHot email IDsShard by hashLarge attachmentsOffload to blobHigh read trafficRedis cacheSpam overloadPre-filter before Kafka</p><div><hr></div><h1>&#129514; APIs</h1><h3>Create Email</h3><pre><code>POST /email
Response:
{
  &#8220;email&#8221;: &#8220;blue-tiger-92@tempmail.com&#8221;,
  &#8220;expires_at&#8221;: &#8220;...&#8221;
}</code></pre><div><hr></div><h3>Get Inbox</h3><pre><code>GET /emails/{email_id}</code></pre><div><hr></div><h3>Get Email Detail</h3><pre><code>GET /emails/{email_id}/{message_id}</code></pre><div><hr></div><h1>&#129504; Interview Tips</h1><ul><li><p>Start with <strong>email infra (SMTP)</strong> &#8594; shows depth<br></p></li><li><p>Emphasize <strong>Kafka for decoupling</strong><br></p></li><li><p>Push on:<br></p><ul><li><p><strong>TTL strategy</strong><br></p></li><li><p><strong>Abuse prevention</strong><br></p></li><li><p><strong>Scaling ingestion vs reads</strong><br></p></li></ul></li></ul><div><hr></div><p><br></p>]]></content:encoded></item><item><title><![CDATA[HLD: Design DB migration platform for a company like TicketMaster transitioning to a nosql based datastore.(Asked in Mongo DB interview)]]></title><description><![CDATA[If you&#8217;re looking for paid 1:1 mentorship with a strong focus on LLD (core emphasis on Multithreading), HLD, DSA, and system design research papers, feel free to reach out.]]></description><link>https://programmingappliedai.substack.com/p/hld-design-db-migration-platform</link><guid isPermaLink="false">https://programmingappliedai.substack.com/p/hld-design-db-migration-platform</guid><dc:creator><![CDATA[Shashank Mishra]]></dc:creator><pubDate>Fri, 10 Apr 2026 16:45:11 GMT</pubDate><enclosure url="iframe.php?url=https%3A%2F%2Fsubstackcdn.com%2Fimage%2Ffetch%2F%24s_%21riGX%21%2Cw_256%2Cc_limit%2Cf_auto%2Cq_auto%3Agood%2Cfl_progressive%3Asteep%2Fhttps%253A%252F%252Fsubstack-post-media.s3.amazonaws.com%252Fpublic%252Fimages%252F58e132e8-cd28-4037-b0ef-feabb2b68221_144x144.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h3><strong>If you&#8217;re looking for paid 1:1 mentorship with a strong focus on LLD (core emphasis on Multithreading), HLD, DSA, and system design research papers, feel free to reach out.</strong></h3><p>&#128233; <strong>Contact:</strong> programmingappliedai@gmail.com</p><p>FR</p><ul><li><p>Support bulk migration of historical data from RDBMS to NoSQL</p></li><li><p>Capture and replicate real-time data changes (CDC) from source to target</p></li><li><p>Transform relational schema into NoSQL-compatible data models</p></li><li><p>Enable dual writes to both databases during migration phase</p></li><li><p>Ensure seamless incremental sync between bulk load and live updates</p></li><li><p>Provide data validation mechanisms (counts, checksums, record-level diff)</p></li><li><p>Support controlled traffic cutover from old DB to new datastore</p></li><li><p>Allow rollback to source database in case of failures</p></li><li><p>Handle write conflicts and ensure consistency during dual-write phase</p></li><li><p>Provide monitoring, alerting, and operational controls (pause/resume/retry)</p></li></ul><p><strong>NFR</strong></p><ul><li><p><strong>High Availability</strong> &#8211; Migration should not cause downtime; ticket booking and browsing must remain continuously available</p></li><li><p><strong>Strong Consistency (Critical Flows)</strong> &#8211; Ensure strict consistency for operations like seat booking to prevent double bookings</p></li><li><p><strong>Scalability</strong> &#8211; System should handle large-scale data (TB&#8211;PB) and high throughput during peak traffic events</p></li><li><p><strong>Fault Tolerance</strong> &#8211; System should recover from failures using retries, idempotent operations, and checkpointing</p></li><li><p><strong>Low Latency Impact</strong> &#8211; Migration (especially dual writes and CDC) should not significantly increase application latency</p></li><li><p><strong>Observability</strong> &#8211; Provide detailed metrics, logging, and alerting for migration progress, lag, errors, and system health</p></li></ul><p><strong>API&#8217;s</strong></p><h2><strong>1. Start Bulk Migration</strong></h2><p><strong>POST</strong> <code>/migration/start</code></p><p><strong>Request:</strong></p><pre><code>{
  &#8220;migrationId&#8221;: &#8220;mig_123&#8221;,
  &#8220;sourceDB&#8221;: &#8220;mysql_cluster_A&#8221;,
  &#8220;targetDB&#8221;: &#8220;cassandra_cluster_B&#8221;,
  &#8220;tables&#8221;: [&#8221;events&#8221;, &#8220;tickets&#8221;, &#8220;bookings&#8221;],
  &#8220;batchSize&#8221;: 10000
}</code></pre><p><strong>Response:</strong></p><pre><code>{
  &#8220;status&#8221;: &#8220;STARTED&#8221;,
  &#8220;migrationId&#8221;: &#8220;mig_123&#8221;
}</code></pre><div><hr></div><h2><strong>2. Get Migration Status</strong></h2><p><strong>GET</strong> <code>/migration/{migrationId}/status</code></p><p><strong>Response:</strong></p><pre><code>{
  &#8220;migrationId&#8221;: &#8220;mig_123&#8221;,
  &#8220;status&#8221;: &#8220;IN_PROGRESS&#8221;,
  &#8220;progress&#8221;: &#8220;65%&#8221;,
  &#8220;lagInMs&#8221;: 1200,
  &#8220;errors&#8221;: 10
}</code></pre><div><hr></div><h2><strong>3. Pause Migration</strong></h2><p><strong>POST</strong> <code>/migration/{migrationId}/pause</code></p><p><strong>Response:</strong></p><pre><code>{
  &#8220;status&#8221;: &#8220;PAUSED&#8221;
}</code></pre><div><hr></div><h2><strong>4. Resume Migration</strong></h2><p><strong>POST</strong> <code>/migration/{migrationId}/resume</code></p><p><strong>Response:</strong></p><pre><code>{
  &#8220;status&#8221;: &#8220;RESUMED&#8221;
}</code></pre><div><hr></div><h2><strong>5. Start CDC (Real-Time Sync)</strong></h2><p><strong>POST</strong> <code>/migration/{migrationId}/cdc/start</code></p><p><strong>Request:</strong></p><pre><code>{
  &#8220;source&#8221;: &#8220;binlog&#8221;,
  &#8220;offset&#8221;: &#8220;log_456&#8221;
}</code></pre><p><strong>Response:</strong></p><pre><code>{
  &#8220;status&#8221;: &#8220;CDC_STARTED&#8221;
}</code></pre><div><hr></div><h2><strong>6. Get CDC Lag</strong></h2><p><strong>GET</strong> <code>/migration/{migrationId}/cdc/lag</code></p><p><strong>Response:</strong></p><pre><code>{
  &#8220;lagInMs&#8221;: 800,
  &#8220;lastSyncedTimestamp&#8221;: &#8220;2026-04-10T10:00:00Z&#8221;
}</code></pre><div><hr></div><h2><strong>7. Validate Data</strong></h2><p><strong>POST</strong> <code>/migration/{migrationId}/validate</code></p><p><strong>Request:</strong></p><pre><code>{
  &#8220;type&#8221;: &#8220;checksum&#8221;,
  &#8220;tables&#8221;: [&#8221;bookings&#8221;]
}</code></pre><p><strong>Response:</strong></p><pre><code>{
  &#8220;status&#8221;: &#8220;VALIDATION_STARTED&#8221;
}</code></pre><div><hr></div><h2><strong>8. Get Validation Report</strong></h2><p><strong>GET</strong> <code>/migration/{migrationId}/validation/report</code></p><p><strong>Response:</strong></p><pre><code>{
  &#8220;status&#8221;: &#8220;COMPLETED&#8221;,
  &#8220;mismatchedRecords&#8221;: 25,
  &#8220;details&#8221;: &#8220;checksum mismatch in bookings&#8221;
}</code></pre><div><hr></div><h2><strong>9. Trigger Cutover</strong></h2><p><strong>POST</strong> <code>/migration/{migrationId}/cutover</code></p><p><strong>Request:</strong></p><pre><code>{
  &#8220;mode&#8221;: &#8220;phased&#8221;,
  &#8220;trafficPercentage&#8221;: 50
}</code></pre><p><strong>Response:</strong></p><pre><code>{
  &#8220;status&#8221;: &#8220;CUTOVER_IN_PROGRESS&#8221;
}</code></pre><div><hr></div><h2><strong>10. Rollback Migration</strong></h2><p><strong>POST</strong> <code>/migration/{migrationId}/rollback</code></p><p><strong>Response:</strong></p><pre><code>{
  &#8220;status&#8221;: &#8220;ROLLED_BACK&#8221;
}</code></pre><div><hr></div><h2><strong>11. Dual Write Toggle</strong></h2><p><strong>POST</strong> <code>/migration/{migrationId}/dual-write</code></p><p><strong>Request:</strong></p><pre><code>{
  &#8220;enabled&#8221;: true
}</code></pre><p><strong>Response:</strong></p><pre><code>{
  &#8220;status&#8221;: &#8220;DUAL_WRITE_ENABLED&#8221;
}</code></pre><p><strong>Databases and Schema</strong></p><h1><strong>Databases Used in Migration Platform</strong></h1><h3><strong>1. Source Database (RDBMS)</strong></h3><ul><li><p>Example: MySQL / PostgreSQL</p></li><li><p>Purpose: Existing transactional system (Ticket booking, inventory)</p></li></ul><div><hr></div><h3><strong>2. Target Database (NoSQL)</strong></h3><ul><li><p>Example: Cassandra / DynamoDB</p></li><li><p>Purpose: Scalable, high-throughput datastore post-migration</p></li></ul><div><hr></div><h3><strong>3. Migration Metadata DB</strong></h3><ul><li><p>Example: PostgreSQL / MySQL</p></li><li><p>Purpose: Track migration jobs, states, checkpoints</p></li></ul><div><hr></div><h3><strong>4. Validation / Audit Store</strong></h3><ul><li><p>Example: S3 / Blob store / Cassandra</p></li><li><p>Purpose: Store validation reports, mismatches</p></li></ul><div><hr></div><h3><strong>5. Cache (Optional)</strong></h3><ul><li><p>Example: Redis</p></li><li><p>Purpose: Speed up reads during dual-read phase</p></li></ul><div><hr></div><h1><strong>Schema Design</strong></h1><div><hr></div><h2><strong>1. Source DB Schema (Relational - Simplified)</strong></h2><h3><strong>Events Table</strong></h3><pre><code>Events(
  event_id BIGINT PRIMARY KEY,
  name VARCHAR,
  venue VARCHAR,
  date TIMESTAMP
)</code></pre><h3><strong>Tickets Table</strong></h3><pre><code>Tickets(
  ticket_id BIGINT PRIMARY KEY,
  event_id BIGINT,
  seat_number VARCHAR,
  price DECIMAL,
  status VARCHAR,  -- AVAILABLE / BOOKED
  FOREIGN KEY (event_id) REFERENCES Events(event_id)
)</code></pre><h3><strong>Bookings Table</strong></h3><pre><code>Bookings(
  booking_id BIGINT PRIMARY KEY,
  user_id BIGINT,
  ticket_id BIGINT,
  status VARCHAR, -- CONFIRMED / CANCELLED
  created_at TIMESTAMP
)</code></pre><p>&#128073; Highly normalized &#8594; joins required</p><div><hr></div><h2><strong>2. Target DB Schema (NoSQL - Cassandra Style)</strong></h2><h3><strong>Design Principle</strong></h3><ul><li><p>Query-driven<br></p></li><li><p>Denormalized<br></p></li><li><p>Avoid joins<br></p></li></ul><div><hr></div><h3><strong>Table: Event_Tickets (Primary Read Path)</strong></h3><pre><code>Event_Tickets(
  event_id,
  seat_number,
  ticket_id,
  price,
  status,
  user_id,
  booking_status,
  PRIMARY KEY (event_id, seat_number)
)</code></pre><p>&#128073; Fetch all seats for an event quickly<br><br>&#128073; Handles seat availability + booking in one place</p><div><hr></div><h3><strong>Table: User_Bookings</strong></h3><pre><code>User_Bookings(
  user_id,
  booking_id,
  event_id,
  ticket_id,
  status,
  created_at,
  PRIMARY KEY (user_id, booking_id)
)</code></pre><p>&#128073; Query bookings per user</p><div><hr></div><h3><strong>Table: Event_Metadata</strong></h3><pre><code>Event_Metadata(
  event_id PRIMARY KEY,
  name,
  venue,
  date
)</code></pre><div><hr></div><h2><strong>3. Migration Metadata DB Schema</strong></h2><h3><strong>Migration Jobs</strong></h3><pre><code>Migration_Jobs(
  migration_id VARCHAR PRIMARY KEY,
  status VARCHAR, -- STARTED / IN_PROGRESS / COMPLETED
  start_time TIMESTAMP,
  end_time TIMESTAMP
)</code></pre><div><hr></div><h3><strong>Table Progress Tracking</strong></h3><pre><code>Migration_Progress(
  migration_id,
  table_name,
  last_processed_pk BIGINT,
  status VARCHAR,
  PRIMARY KEY (migration_id, table_name)
)</code></pre><p>&#128073; Used for checkpointing + resume</p><div><hr></div><h3><strong>CDC Offsets</strong></h3><pre><code>CDC_Offsets(
  migration_id,
  source,
  offset VARCHAR,
  updated_at TIMESTAMP,
  PRIMARY KEY (migration_id, source)
)</code></pre><p>&#128073; Tracks binlog/Kafka offset</p><div><hr></div><h2><strong>4. Validation / Audit Schema</strong></h2><h3><strong>Validation Results</strong></h3><pre><code>Validation_Results(
  migration_id,
  table_name,
  total_records_source BIGINT,
  total_records_target BIGINT,
  mismatch_count BIGINT,
  status VARCHAR,
  PRIMARY KEY (migration_id, table_name)
)</code></pre><div><hr></div><h3><strong>Mismatch Records (Optional)</strong></h3><pre><code>Mismatch_Records(
  migration_id,
  table_name,
  record_id,
  source_value TEXT,
  target_value TEXT
)</code></pre><div><hr></div><h1><strong>Key Design Insights (Interview Gold)</strong></h1><ul><li><p><strong>Denormalization in NoSQL</strong> &#8594; avoids joins, improves latency<br></p></li><li><p><strong>Multiple tables per query pattern</strong> &#8594; common in Cassandra<br></p></li><li><p><strong>Checkpointing via Migration_Progress</strong> &#8594; ensures fault tolerance<br></p></li><li><p><strong>CDC offsets</strong> &#8594; critical for exactly-once / no data loss<br></p></li><li><p><strong>Event_Tickets table</strong> &#8594; solves <em>seat consistency + fast lookup</em><br></p></li></ul><div><hr></div><div><hr></div><h1><strong>Microservices in DB Migration Platform</strong></h1><div><hr></div><h2><strong>1. Migration Orchestrator Service</strong></h2><p><strong>Responsibility:</strong></p><ul><li><p>Central controller of migration lifecycle</p></li><li><p>Starts/stops jobs, manages phases (bulk &#8594; CDC &#8594; cutover)</p></li></ul><p><strong>Key tasks:</strong></p><ul><li><p>Trigger bulk migration</p></li><li><p>Start/stop CDC</p></li><li><p>Initiate cutover / rollback</p></li><li><p>Maintain state machine</p></li></ul><div><hr></div><h2><strong>2. Bulk Migration Service</strong></h2><p><strong>Responsibility:</strong></p><ul><li><p>Migrate historical data from RDBMS &#8594; NoSQL</p></li></ul><p><strong>Key tasks:</strong></p><ul><li><p>Read data in batches</p></li><li><p>Transform schema (normalize &#8594; denormalize)</p></li><li><p>Write to NoSQL</p></li><li><p>Update checkpoints</p></li></ul><div><hr></div><h2><strong>3. CDC (Change Data Capture) Service</strong></h2><p><strong>Responsibility:</strong></p><ul><li><p>Capture real-time changes from source DB</p></li></ul><p><strong>Key tasks:</strong></p><ul><li><p>Read binlogs (Debezium/Kafka)</p></li><li><p>Convert events &#8594; NoSQL format</p></li><li><p>Push to stream (Kafka)</p></li></ul><div><hr></div><h2><strong>4. Stream Processing / Replication Service</strong></h2><p><strong>Responsibility:</strong></p><ul><li><p>Apply CDC events to NoSQL</p></li></ul><p><strong>Key tasks:</strong></p><ul><li><p>Consume Kafka topics</p></li><li><p>Ensure ordering (per key)</p></li><li><p>Idempotent writes</p></li><li><p>Conflict resolution</p></li></ul><div><hr></div><h2><strong>5. Schema Transformation Service</strong></h2><p><strong>Responsibility:</strong></p><ul><li><p>Convert relational schema &#8594; NoSQL model</p></li></ul><p><strong>Key tasks:</strong></p><ul><li><p>Flatten joins</p></li><li><p>Build denormalized records</p></li><li><p>Maintain mapping rules</p></li></ul><div><hr></div><h2><strong>6. Dual Write Proxy Service</strong></h2><p><strong>Responsibility:</strong></p><ul><li><p>Enable application to write to both DBs</p></li></ul><p><strong>Key tasks:</strong></p><ul><li><p>Intercept write requests</p></li><li><p>Write to RDBMS + NoSQL</p></li><li><p>Handle partial failures (retry / compensate)</p></li></ul><div><hr></div><h2><strong>7. Validation Service</strong></h2><p><strong>Responsibility:</strong></p><ul><li><p>Ensure data correctness</p></li></ul><p><strong>Key tasks:</strong></p><ul><li><p>Row count validation</p></li><li><p>Checksums</p></li><li><p>Record-level diff</p></li><li><p>Generate reports</p></li></ul><div><hr></div><h2><strong>8. Cutover Service</strong></h2><p><strong>Responsibility:</strong></p><ul><li><p>Switch traffic from RDBMS &#8594; NoSQL</p></li></ul><p><strong>Key tasks:</strong></p><ul><li><p>Gradual traffic shift (0% &#8594; 100%)</p></li><li><p>Enable shadow reads</p></li><li><p>Monitor errors</p></li></ul><div><hr></div><h2><strong>9. Rollback Service</strong></h2><p><strong>Responsibility:</strong></p><ul><li><p>Revert to old system if needed</p></li></ul><p><strong>Key tasks:</strong></p><ul><li><p>Redirect traffic back</p></li><li><p>Disable dual writes</p></li><li><p>Ensure consistency</p></li></ul><div><hr></div><h2><strong>10. Monitoring &amp; Observability Service</strong></h2><p><strong>Responsibility:</strong></p><ul><li><p>System visibility</p></li></ul><p><strong>Key tasks:</strong></p><ul><li><p>Track lag (CDC)</p></li><li><p>Migration progress</p></li><li><p>Error rates</p></li><li><p>Alerts</p></li></ul><div><hr></div><h1><strong>Interaction Flow (End-to-End)</strong></h1><div><hr></div><h2><strong>Phase 1: Bulk Migration</strong></h2><ol><li><p>Orchestrator &#8594; triggers Bulk Migration Service</p></li><li><p>Bulk Service:</p><ul><li><p>Reads from RDBMS</p></li><li><p>Calls Schema Transformer</p></li><li><p>Writes to NoSQL</p></li></ul></li><li><p>Updates checkpoints in Metadata DB</p></li></ol><div><hr></div><h2><strong>Phase 2: Real-Time Sync (CDC)</strong></h2><ol><li><p>CDC Service:</p><ul><li><p>Reads binlogs &#8594; pushes to Kafka</p></li></ul></li><li><p>Stream Processor:</p><ul><li><p>Consumes events</p></li><li><p>Transforms + writes to NoSQL</p></li></ul></li><li><p>Offsets stored for recovery</p></li></ol><div><hr></div><h2><strong>Phase 3: Dual Writes</strong></h2><ol><li><p>Application &#8594; Dual Write Proxy</p></li><li><p>Proxy:</p><ul><li><p>Writes to RDBMS</p></li><li><p>Writes to NoSQL</p></li></ul></li><li><p>Handles failures with retries / idempotency</p></li></ol><div><hr></div><h2><strong>Phase 4: Validation</strong></h2><ol><li><p>Validation Service:</p><ul><li><p>Compares source vs target</p></li><li><p>Generates reports</p></li></ul></li><li><p>Orchestrator decides readiness</p></li></ol><div><hr></div><h2><strong>Phase 5: Cutover</strong></h2><ol><li><p>Cutover Service:</p><ul><li><p>Gradually shifts reads to NoSQL</p></li><li><p>Then writes fully to NoSQL</p></li></ul></li><li><p>Shadow reads verify correctness</p></li></ol><div><hr></div><h2><strong>Phase 6: Rollback (if needed)</strong></h2><ol><li><p>Rollback Service:</p><ul><li><p>Redirects traffic back to RDBMS</p></li><li><p>Stops CDC / dual writes</p></li></ul></li></ol><div><hr></div><h1><strong>High-Level Interaction Diagram (Textual)</strong></h1><pre><code>Client
  &#8595;
Dual Write Proxy
  &#8595;              &#8600;
RDBMS         NoSQL

RDBMS &#8594; CDC Service &#8594; Kafka &#8594; Stream Processor &#8594; NoSQL

Bulk Migration Service &#8594; NoSQL

Validation Service &#8596; RDBMS &amp; NoSQL

Orchestrator &#8594; Controls all services</code></pre><div><hr></div><h1><strong>Key Design Insights (What interviewer looks for)</strong></h1><ul><li><p><strong>Decoupling via Kafka</strong> &#8594; avoids tight coupling between CDC and writes<br></p></li><li><p><strong>Idempotent consumers</strong> &#8594; ensures no duplicate writes<br></p></li><li><p><strong>Partitioning by event_id / ticket_id</strong> &#8594; preserves ordering<br></p></li><li><p><strong>Dual write + CDC overlap</strong> &#8594; ensures zero data loss<br></p></li><li><p><strong>Shadow reads before cutover</strong> &#8594; reduces risk<br></p></li></ul><div><hr></div><p>If you want to go <strong>next level (staff-level discussion)</strong>, I can explain:</p><ul><li><p>Exactly-once semantics in CDC pipeline<br></p></li><li><p>Handling <strong>seat booking consistency in Cassandra (LWT vs Redis locks)</strong><br></p></li><li><p>Or failure scenarios (Kafka lag, partial writes, replay strategies) &#128640;<br></p></li></ul><p>flow diagram</p><p>Here&#8217;s a <strong>clean, interview-ready flow diagram</strong> you can draw on a whiteboard &#128071;</p><div><hr></div><h1><strong>DB Migration Platform &#8211; Flow Diagram</strong></h1><pre><code>                  +----------------------+
                  |   Migration          |
                  |   Orchestrator       |
                  +----------+-----------+
                             |
        -----------------------------------------------
        |                     |                      |
        &#8595;                     &#8595;                      &#8595;

+----------------+   +----------------+    +----------------+
| Bulk Migration |   |   CDC Service  |    |  Validation    |
|   Service      |   | (Binlog Reader)|    |   Service      |
+--------+-------+   +--------+-------+    +--------+-------+
         |                    |                     |
         &#8595;                    &#8595;                     |
   +------------+     +---------------+            |
   |  RDBMS     |----&gt;|    Kafka      |------------+
   +------------+     +-------+-------+
                               |
                               &#8595;
                      +----------------------+
                      | Stream Processor     |
                      | (Replication Layer)  |
                      +----------+-----------+
                                 |
                                 &#8595;
                         +--------------+
                         |   NoSQL DB   |
                         +--------------+

------------------------------------------------------------

                 (Application Traffic Flow)

                     +------------------+
Client  -----------&gt; | Dual Write Proxy |
                     +--------+---------+
                              |
                  -------------------------
                  |                       |
                  &#8595;                       &#8595;
             +---------+           +------------+
             |  RDBMS  |           |  NoSQL DB  |
             +---------+           +------------+

------------------------------------------------------------

                 (Cutover Phase)

Client  -------------------------------------&gt; NoSQL DB
                     (RDBMS removed gradually)</code></pre><div><hr></div><h1><strong>How to Explain This in Interview (Quick Script)</strong></h1><ul><li><p><strong>Top layer</strong> &#8594; Orchestrator controls everything<br></p></li><li><p><strong>Left path</strong> &#8594; Bulk migration moves historical data<br></p></li><li><p><strong>Middle path</strong> &#8594; CDC + Kafka handles real-time updates<br></p></li><li><p><strong>Right path</strong> &#8594; Validation ensures correctness<br></p></li><li><p><strong>Bottom</strong> &#8594; Dual writes keep both DBs in sync<br></p></li><li><p><strong>Final step</strong> &#8594; Cutover shifts traffic fully to NoSQL<br></p></li></ul><div><hr></div><h1></h1><p></p><p><br></p>]]></content:encoded></item></channel></rss>