<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Technical Deep Dives on Ou David | Systems Engineer</title><link>https://preview.vvivid.dev/categories/technical-deep-dives/</link><description>Recent content in Technical Deep Dives on Ou David | Systems Engineer</description><generator>Hugo -- gohugo.io</generator><language>en-us</language><lastBuildDate>Mon, 15 Jun 2026 13:31:48 +0700</lastBuildDate><atom:link href="https://preview.vvivid.dev/categories/technical-deep-dives/index.xml" rel="self" type="application/rss+xml"/><item><title>The Process API Behind Every Shell Command</title><link>https://preview.vvivid.dev/posts/process_api_behind_every_shell_command/</link><pubDate>Mon, 15 Jun 2026 13:31:48 +0700</pubDate><guid>https://preview.vvivid.dev/posts/process_api_behind_every_shell_command/</guid><description>&lt;p&gt;I&amp;rsquo;ve been reading &lt;a href="https://pages.cs.wisc.edu/~remzi/OSTEP/"&gt;Operating Systems: Three Easy Pieces&lt;/a&gt;, and today I went through chapter 05, the interlude on the Process API. It is a short chapter, but it clarified something important about how processes actually work.&lt;/p&gt;
&lt;p&gt;If you want to see the same idea in practical Go code, I put a small runnable example in the public case-study repo: &lt;a href="https://gitlab.vvivid.dev/showcase/go-lang-case-study/-/tree/main/go/process-api-shell"&gt;go/process-api-shell&lt;/a&gt;. It uses Go&amp;rsquo;s standard &lt;code&gt;os/exec&lt;/code&gt; package to run commands, redirect output, build a simple pipeline, and wait for the processes to finish.&lt;/p&gt;</description></item><item><title>String Concatenation vs strings.Builder in Go</title><link>https://preview.vvivid.dev/posts/go_string_concat_vs_string_builder/</link><pubDate>Sat, 13 Jun 2026 10:34:19 +0700</pubDate><guid>https://preview.vvivid.dev/posts/go_string_concat_vs_string_builder/</guid><description>&lt;p&gt;I often leave the same comment when I see string concatenation inside a loop:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;If you build a string in a loop, use &lt;code&gt;strings.Builder&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;That comment sometimes gets pushback from the team: the two operations probably will not matter much. Today, I want to show a simple benchmark to demonstrate why &lt;code&gt;strings.Builder&lt;/code&gt; is superior to doing &lt;code&gt;+=&lt;/code&gt; inside a loop.&lt;/p&gt;
&lt;p&gt;The runnable code and raw benchmark output are available in the public repo: &lt;a href="https://gitlab.vvivid.dev/showcase/go-lang-case-study"&gt;gitlab.vvivid.dev/showcase/go-lang-case-study&lt;/a&gt;.&lt;/p&gt;</description></item><item><title>The Trap of Vibe Coding for Juniors</title><link>https://preview.vvivid.dev/posts/the_trap_of_vibe_coding_for_juniors/</link><pubDate>Tue, 27 Jan 2026 12:00:00 +0700</pubDate><guid>https://preview.vvivid.dev/posts/the_trap_of_vibe_coding_for_juniors/</guid><description>&lt;p&gt;Today I want to write about something different: &lt;strong&gt;vibe coding&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;My honest opinion is that vibe coding is risky for junior developers. Not because AI is bad at writing code. The real problem is that juniors often do not have enough experience yet to judge whether the generated solution is correct, maintainable, or safe under production pressure.&lt;/p&gt;
&lt;p&gt;That is where the trap starts. The code works once, the demo looks good, and the feature feels finished. But working code is not always good code.&lt;/p&gt;</description></item><item><title>Handling Fractional Cents in Integrations</title><link>https://preview.vvivid.dev/posts/handling_fractional_cents_integration/</link><pubDate>Wed, 21 Jan 2026 08:48:01 +0100</pubDate><guid>https://preview.vvivid.dev/posts/handling_fractional_cents_integration/</guid><description>&lt;p&gt;I&amp;rsquo;m back with another story about a &amp;ldquo;silent error&amp;rdquo; in our systems. In my &lt;a href="https://preview.vvivid.dev/posts/the_silent_timezone_mismatch_go_vs_mongodb"&gt;previous post&lt;/a&gt;, I talked about how implicit timezone conversions can bite you. Today, let&amp;rsquo;s talk about a different type of error: a design flaw when dealing with money.&lt;/p&gt;
&lt;h3 id="the-real-problem"&gt;The Real Problem&lt;/h3&gt;
&lt;p&gt;We are building a Central Reservation System (CRS) for a tourist park. One of our golden rules when dealing with money is simple: &lt;strong&gt;always use integers&lt;/strong&gt;. We convert everything to cents before pushing it to our cash-register API.&lt;/p&gt;</description></item><item><title>The Silent Timezone Mismatch: Go vs MongoDB</title><link>https://preview.vvivid.dev/posts/the_silent_timezone_mismatch_go_vs_mongodb/</link><pubDate>Fri, 16 Jan 2026 18:33:20 +0100</pubDate><guid>https://preview.vvivid.dev/posts/the_silent_timezone_mismatch_go_vs_mongodb/</guid><description>&lt;p&gt;I recently encountered a subtle bug that cost more time than I&amp;rsquo;d like to admit. It’s a classic example of how implicit defaults in our tools can lead to unexpected behavior in distributed systems.&lt;/p&gt;
&lt;h3 id="the-real-problem"&gt;The Real Problem&lt;/h3&gt;
&lt;p&gt;I was implementing a validation function, &lt;code&gt;isValidCiaoPayment&lt;/code&gt;. The logic was simple: check if a payment record from MongoDB matches a specific check date (e.g., &amp;ldquo;2026-01-15&amp;rdquo;).&lt;/p&gt;
&lt;p&gt;Here is the logic:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;// Convert payment time to string YYYY-MM-DD&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nx"&gt;paymentUpdatedAtDate&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;payment&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;UpdatedAt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Time&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;Format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;DateOnly&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;// Compare with the target date&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;paymentUpdatedAtDate&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;!=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;checkDate&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The function kept returning &lt;code&gt;false&lt;/code&gt; even when the data looked correct in the database.&lt;/p&gt;</description></item><item><title>Building a JSON-RPC Server in Go: Complete Implementation Guide</title><link>https://preview.vvivid.dev/posts/jsonrpc_example/</link><pubDate>Sat, 30 Aug 2025 10:00:00 +0000</pubDate><guid>https://preview.vvivid.dev/posts/jsonrpc_example/</guid><description>&lt;p&gt;Last week, I posted about &lt;a href="https://preview.vvivid.dev/posts/json_rpc_the_protocol_behind_mcp/"&gt;JSON-RPC and the Model Context Protocol&lt;/a&gt;. Today, we&amp;rsquo;re going to see an example of how we can create a simple application following the JSON-RPC standard. We&amp;rsquo;ll build a simple JSON-RPC calculator together, and I hope you&amp;rsquo;ll enjoy it.&lt;/p&gt;
&lt;h2 id="request-flow-overview"&gt;Request Flow Overview&lt;/h2&gt;
&lt;div class="mermaid"&gt;
flowchart LR
A[Client Request] --&gt; B[Parse JSON]
B --&gt; C{Valid?}
C --&gt;|No| D[Error Response]
C --&gt;|Yes| E{Type?}
E --&gt;|Request| F[Match Method]
E --&gt;|Notification| G[Execute &amp; End]
F --&gt; H{Method Found?}
H --&gt;|No| I[Method Not Found]
H --&gt;|Yes| J[Execute Method]
J --&gt; K[Build Response]
I --&gt; K
K --&gt; L[Send Response]
D --&gt; L
L --&gt; M[End]
G --&gt; M
&lt;/div&gt;&lt;h2 id="message-parsing-and-validation"&gt;Message Parsing and Validation&lt;/h2&gt;
&lt;p&gt;Let&amp;rsquo;s recap JSON-RPC message types. We have 3 types of messages: Request, Response, and Notification. For request and response types, we can send them in batches, and responses must be returned in a batch matching the request IDs in any order. We can distinguish between a request and a notification by checking the ID field. If there&amp;rsquo;s an ID, it&amp;rsquo;s a request; if not, it&amp;rsquo;s a notification.&lt;/p&gt;</description></item><item><title>Understanding JSON-RPC: The Protocol Behind MCP</title><link>https://preview.vvivid.dev/posts/json_rpc_the_protocol_behind_mcp/</link><pubDate>Sun, 24 Aug 2025 00:00:00 +0000</pubDate><guid>https://preview.vvivid.dev/posts/json_rpc_the_protocol_behind_mcp/</guid><description>&lt;p&gt;I&amp;rsquo;ve been diving into the &lt;a href="https://modelcontextprotocol.io/"&gt;Model Context Protocol (MCP)&lt;/a&gt; lately. Honestly, it&amp;rsquo;s the most exciting thing happening in AI infrastructure right now. But here&amp;rsquo;s the thing: to really understand MCP, you need to understand &lt;a href="https://www.jsonrpc.org/specification"&gt;JSON-RPC&lt;/a&gt; first. That&amp;rsquo;s what MCP is built on.&lt;/p&gt;
&lt;p&gt;So let me break down JSON-RPC for you. Once you get this, MCP will make way more sense.&lt;/p&gt;
&lt;p&gt;First, let&amp;rsquo;s talk about how JSON-RPC is different from the REST APIs we&amp;rsquo;re all used to. REST is stateless and unidirectional where each request is independent. Check this out:&lt;/p&gt;</description></item><item><title>The HTTP Request Journey in Go: From Network to Handler</title><link>https://preview.vvivid.dev/posts/http_in_golang/</link><pubDate>Fri, 08 Aug 2025 10:00:00 +0000</pubDate><guid>https://preview.vvivid.dev/posts/http_in_golang/</guid><description>&lt;p&gt;As a backend guy, I&amp;rsquo;ve been tasked with building various APIs for different projects, and most of them I built using Go. For the majority of the time, what most people do is write a handler or middleware to process and respond to requests. Today, we&amp;rsquo;re going to do something different. We&amp;rsquo;ll go down a rabbit hole together into the abstractions that Go has taken away from us. We&amp;rsquo;ll see all the interesting things that Go does before handing us the request and response objects in our handler. After this deep dive, we&amp;rsquo;ll understand how to parse requests, how routing matching works, middleware execution, and finally the architecture that Go uses to handle each request.&lt;/p&gt;</description></item></channel></rss>