<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Go on Vivek's Field Notes</title><link>https://heyyviv.github.io/tags/go/</link><description>Recent content in Go on Vivek's Field Notes</description><generator>Hugo</generator><language>en-us</language><lastBuildDate>Sun, 12 Jul 2026 00:00:00 +0000</lastBuildDate><atom:link href="https://heyyviv.github.io/tags/go/index.xml" rel="self" type="application/rss+xml"/><item><title>Building a Better Narad: Open-Source Reference Architectures, Algorithms, and Technical Literature</title><link>https://heyyviv.github.io/blog/building-a-better-narad-open-source-reference-architectures-algorithms-and-technical-literature/</link><pubDate>Sun, 12 Jul 2026 00:00:00 +0000</pubDate><guid>https://heyyviv.github.io/blog/building-a-better-narad-open-source-reference-architectures-algorithms-and-technical-literature/</guid><description>&lt;p>&lt;strong>Narad&lt;/strong> is a high-performance, self-hosted log intelligence platform built for microservices. It ingests structured logs with business dimensions via Apache Kafka, stores them in TimescaleDB, and enables cross-service request tracing and dimension querying.&lt;/p>
&lt;p>To take Narad from a high-throughput queue-to-db worker to an enterprise-ready log intelligence system, we don&amp;rsquo;t have to reinvent the wheel. We can study the architectures, codebases, and academic papers of industry-defining open-source systems.&lt;/p>
&lt;p>Here is a curated guide to the open-source codebases, specific module implementations, and technical papers that will help us make Narad faster, more reliable, and smarter.&lt;/p>
&lt;hr>
&lt;h2 id="1-high-throughput-ingestion--database-modeling">1. High-Throughput Ingestion &amp;amp; Database Modeling&lt;/h2>
&lt;h3 id="reference-promscale-timescaledb">Reference: Promscale (TimescaleDB)&lt;/h3>
&lt;ul>
&lt;li>&lt;strong>The Code:&lt;/strong> &lt;a href="https://github.com/timescale/promscale">github.com/timescale/promscale&lt;/a>&lt;/li>
&lt;li>&lt;strong>Specific Module:&lt;/strong> &lt;code>/pkg/pgmodel&lt;/code>&lt;/li>
&lt;li>&lt;strong>What to Learn:&lt;/strong> Promscale was Timescale&amp;rsquo;s official connector for storing Prometheus metrics and OpenTelemetry logs/traces in TimescaleDB. Although discontinued in 2023, its Go codebase is the absolute gold standard for how to write high-frequency telemetry data to PostgreSQL.&lt;/li>
&lt;li>&lt;strong>Implementation Detail:&lt;/strong> Study how Promscale utilizes the PostgreSQL binary &lt;code>COPY&lt;/code> protocol via &lt;code>pgx.Conn.CopyFrom&lt;/code> instead of individual or batched &lt;code>INSERT&lt;/code> queries. It implements custom batchers and queue workers in Go that accumulate logs in memory (or temporary staging tables) and stream them directly into database buffers. This achieves &lt;strong>50–100x&lt;/strong> the throughput of standard inserts.&lt;/li>
&lt;/ul>
&lt;h3 id="technical-article-design-patterns-for-high-throughput-ingestion-in-timescaledb">Technical Article: &amp;ldquo;Design Patterns for High-Throughput Ingestion in TimescaleDB&amp;rdquo;&lt;/h3>
&lt;ul>
&lt;li>&lt;strong>The Resource:&lt;/strong> TimescaleDB Engineering Blog &amp;amp; Technical Documentation&lt;/li>
&lt;li>&lt;strong>Key Concept:&lt;/strong> Data partitioning (chunks) and chronological order insertion. TimescaleDB partitions hypertables on time. Appending logs in loose time-series order allows PostgreSQL to keep only the latest time-chunk index in memory, preventing heavy disk-thrashing random I/O. We must ensure Narad workers batch and sort logs chronologically before flushing them to TimescaleDB.&lt;/li>
&lt;/ul>
&lt;hr>
&lt;h2 id="2-dimension-first--metadata-indexing">2. Dimension-First / Metadata Indexing&lt;/h2>
&lt;h3 id="reference-grafana-loki">Reference: Grafana Loki&lt;/h3>
&lt;ul>
&lt;li>&lt;strong>The Code:&lt;/strong> &lt;a href="https://github.com/grafana/loki">github.com/grafana/loki&lt;/a>&lt;/li>
&lt;li>&lt;strong>Specific Module:&lt;/strong> &lt;code>/pkg/logql&lt;/code> and &lt;code>/pkg/iter&lt;/code>&lt;/li>
&lt;li>&lt;strong>What to Learn:&lt;/strong> Loki revolutionized logging by choosing &lt;strong>not&lt;/strong> to index the raw log text. Instead, it indexes only the metadata/labels (e.g. &lt;code>service&lt;/code>, &lt;code>env&lt;/code>, &lt;code>customer_id&lt;/code>) and stores the raw text compressed in object chunks. This matches Narad&amp;rsquo;s &amp;ldquo;Dimension-First&amp;rdquo; philosophy.&lt;/li>
&lt;li>&lt;strong>Implementation Detail:&lt;/strong> Examine how Loki stores and aggregates labels. Their label index maps key-value combinations to chunk references. In Narad, our &lt;code>log_dims&lt;/code> table is a direct relational analogue to Loki&amp;rsquo;s label store. We can study Loki&amp;rsquo;s query engine to optimize query planner performance when filtering by dynamic key-value maps.&lt;/li>
&lt;/ul>
&lt;h3 id="technical-concept-clickhouse-sparse-indexing">Technical Concept: ClickHouse Sparse Indexing&lt;/h3>
&lt;ul>
&lt;li>&lt;strong>Key Concept:&lt;/strong> Instead of index lookups pointing to single rows, ClickHouse uses sparse primary indexes that mark the boundaries of data blocks (granules). We can adopt a similar approach to database indexing for &lt;code>log_dims&lt;/code>. By indexing &lt;code>(key, value, log_ts DESC)&lt;/code>, we can quickly narrow down the query search space to specific hypertable chunks.&lt;/li>
&lt;/ul>
&lt;hr>
&lt;h2 id="3-distributed-tracing--context-propagation">3. Distributed Tracing &amp;amp; Context Propagation&lt;/h2>
&lt;h3 id="technical-paper-dapper-a-large-scale-distributed-systems-tracing-infrastructure-google-2010">Technical Paper: &amp;ldquo;Dapper, a Large-Scale Distributed Systems Tracing Infrastructure&amp;rdquo; (Google, 2010)&lt;/h3>
&lt;ul>
&lt;li>&lt;strong>The Resource:&lt;/strong> Google Technical Report (2010)&lt;/li>
&lt;li>&lt;strong>Key Concept:&lt;/strong> The foundational paper that defines how distributed tracing works: propagating metadata across network boundaries (via headers) using &lt;code>Trace ID&lt;/code> and &lt;code>Span ID&lt;/code> to reconstruct a causal chain of events.&lt;/li>
&lt;li>&lt;strong>Implementation Detail:&lt;/strong> Narad implements a &lt;code>trace_request&lt;/code> endpoint to follow requests across microservices. To make this seamless, Narad should conform to the &lt;strong>W3C Trace Context Specification&lt;/strong>. If a log comes in with standard headers like &lt;code>traceparent&lt;/code> (&lt;code>00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-01&lt;/code>), Narad should automatically extract the trace ID (&lt;code>4bf92f3577b34da6a3ce929d0e0e4736&lt;/code>) and span ID (&lt;code>00f067aa0ba902b7&lt;/code>) and register them as native dimensions.&lt;/li>
&lt;/ul>
&lt;hr>
&lt;h2 id="4-pipeline-resilience--backpressure">4. Pipeline Resilience &amp;amp; Backpressure&lt;/h2>
&lt;h3 id="reference-vector-by-datadog">Reference: Vector (by Datadog)&lt;/h3>
&lt;ul>
&lt;li>&lt;strong>The Code:&lt;/strong> &lt;a href="https://github.com/vectordotdev/vector">github.com/vectordotdev/vector&lt;/a>&lt;/li>
&lt;li>&lt;strong>Specific Module:&lt;/strong> &lt;code>src/buffers&lt;/code> (Rust)&lt;/li>
&lt;li>&lt;strong>What to Learn:&lt;/strong> Vector is a lightweight, ultra-fast observability agent. One of its strongest features is how it handles buffering and backpressure when downstream databases (like TimescaleDB) slow down.&lt;/li>
&lt;li>&lt;strong>Implementation Detail:&lt;/strong> Vector supports dual-mode buffering: fast in-memory queues that spill over to disk-backed buffers (write-ahead log files on disk) when the memory limit is exceeded. We can implement a simplified file-spill buffer queue in the Narad worker. If TimescaleDB experiences a heavy lock or lock wait, the worker can temporarily serialize incoming Kafka batches to local disk files, preventing the consumer lag from growing infinitely and saving system RAM.&lt;/li>
&lt;/ul>
&lt;hr>
&lt;h2 id="summary-of-the-narad-roadmap">Summary of the Narad Roadmap&lt;/h2>
&lt;p>By merging the lessons of these systems, we can define a clear path to make Narad a powerhouse:&lt;/p>
&lt;ol>
&lt;li>&lt;strong>Ingestion:&lt;/strong> Refactor &lt;code>InsertLogBatch&lt;/code> to use &lt;code>pgx.CopyFrom&lt;/code> for native bulk inserts.&lt;/li>
&lt;li>&lt;strong>Context:&lt;/strong> Auto-parse OTel &lt;code>traceparent&lt;/code> context format inside our parser pipeline.&lt;/li>
&lt;li>&lt;strong>Database:&lt;/strong> Run migrations to set up automatic columnar compression and drop-chunk retention policies on TimescaleDB.&lt;/li>
&lt;li>&lt;strong>Buffering:&lt;/strong> Implement a disk-spill buffer queue in Go for database write failures.&lt;/li>
&lt;/ol></description></item></channel></rss>