<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet href="pretty-atom-feed.xsl" type="text/xsl"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
  <title>Shannon&#39;s Software Engineering Blog</title>
  <subtitle>Just software stuff.</subtitle>
  <link href="https://sh4nnongoh.github.io/feed/feed.xml" rel="self" />
  <link href="https://sh4nnongoh.github.io/" />
  <updated>2026-03-24T00:00:00Z</updated>
  <id>https://sh4nnongoh.github.io/</id>
  <author>
    <name>Shannon Goh</name>
  </author>
  <entry>
    <title>Project — Agentic DDD Platform</title>
    <link href="https://sh4nnongoh.github.io/blog/11-agentic-ddd-platform/" />
    <updated>2026-03-24T00:00:00Z</updated>
    <id>https://sh4nnongoh.github.io/blog/11-agentic-ddd-platform/</id>
    <content type="html">&lt;br&gt;
&lt;br&gt;
&lt;div class=&quot;message-box&quot;&gt;
	&lt;p&gt;&lt;em&gt;
  This post is still a work-in-progress, and will most likely be worked-on in stealth mode. (:
  &lt;/em&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;Before diving deeper into the Agentic Workflow space, let&#39;s work on a project to have some direction.&lt;/p&gt;
&lt;p&gt;Domain Driven Design (DDD) has a large influence on how I think about systems, but is hard to apply effectively, especially when working in teams within an organization who do not know much about it.&lt;/p&gt;
&lt;p&gt;Now that Agentic Workflows are becoming the norm, and LLMs can heavily abstract away the mechanics of applying DDD effectively, this seems like a good project to work on.&lt;/p&gt;
&lt;h2 id=&quot;agentic-ddd-platform&quot;&gt;Agentic DDD Platform&lt;/h2&gt;
&lt;p&gt;The DDD methodology provides a framework from converting formal business language into working systems. By having visibility into actual business workflows, an engineer can effectively implement just enough features to meet business objectives, hence reducing the overall complexity, and achieving maximum impact or value creation.&lt;/p&gt;
&lt;p&gt;The goal of this platform is to translate a business from a user&#39;s point-of-view, described by a business domain expert, and construct deployable technical artifacts to create a minimal working system to meet those business needs.&lt;/p&gt;
&lt;p&gt;The inputs will be from 2 personas: (1) Domain Expert; (2) Software Engineer. The domain expert will describe the user interactions with the system, and the software engineer will enhance the intermediary artifacts generated by the platform from the domain expert&#39;s input. The platform will support multiple iterations between the domain expert and the software engineer before generating outputs. This output construct will be in the form of multiple technical artifacts like code, binaries, containers, infrastructure-as-code descriptions, etc, which the software engineer will use to deploy the system.&lt;/p&gt;
&lt;p&gt;The value of this platform is in the iterative collaboration aspect between technical and non-technical folks. When building a large system, it is largely a discovery process where the constraints may not be known upfront; i.e. its not possible to fully describe an entire system in a few prompts or a markdown file. By building iteratively, the team can create checkpoints at various points in the project lifecycle and branch out when an idea or experiment does not work.&lt;/p&gt;
&lt;h3 id=&quot;table-of-contents&quot;&gt;Table of Contents&lt;/h3&gt;
&lt;hr&gt;
&lt;div class=&quot;message-box&quot;&gt;
	&lt;p&gt;&lt;em&gt;The structure of this System Design document is explained in this &lt;a href=&quot;https://sh4nnongoh.github.io/blog/2-system-design&quot;&gt;post&lt;/a&gt;.&lt;br&gt;&lt;/em&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href=&quot;https://sh4nnongoh.github.io/blog/11-agentic-ddd-platform/#ddd-strategic-design&quot;&gt;DDD Strategic Design&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://sh4nnongoh.github.io/blog/11-agentic-ddd-platform/#ddd-tactical-design&quot;&gt;DDD Tactical Design&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://sh4nnongoh.github.io/blog/11-agentic-ddd-platform/#non-functional-requirements&quot;&gt;Non-Functional Requirements&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://sh4nnongoh.github.io/blog/11-agentic-ddd-platform/#api-endpoints&quot;&gt;API Endpoints&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://sh4nnongoh.github.io/blog/11-agentic-ddd-platform/#capacity-estimation&quot;&gt;Capacity Estimation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://sh4nnongoh.github.io/blog/11-agentic-ddd-platform/#cost-estimation&quot;&gt;Cost Estimation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://sh4nnongoh.github.io/blog/11-agentic-ddd-platform/#system-architecture&quot;&gt;System Architecture&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id=&quot;system-design&quot;&gt;System Design&lt;/h3&gt;
&lt;hr&gt;
&lt;h4 id=&quot;ddd-strategic-design&quot;&gt;&lt;strong&gt;DDD Strategic Design&lt;/strong&gt;&lt;/h4&gt;
&lt;div class=&quot;simple-table-container&quot;&gt;
  &lt;table class=&quot;simple-table&quot;&gt;
    &lt;thead&gt;
      &lt;tr&gt;
        &lt;th&gt;Persona&lt;/th&gt;
        &lt;th&gt;Interaction&lt;/th&gt;
      &lt;/tr&gt;
    &lt;/thead&gt;
    &lt;tbody&gt;
      &lt;tr&gt;
        &lt;td&gt;Expert&lt;/td&gt;
        &lt;td&gt;
          Enters a prompt in the Role-Feature-Reason format 
          describing the business from a certain user&#39;s point-of-view, 
          so that an agent can create a System Design document from the prompt.
        &lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
        &lt;td&gt;Expert&lt;/td&gt;
        &lt;td&gt;Reviews &amp; edit the generated System Design document (non-technical) so that it can be as accurate as possible.&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
        &lt;td&gt;Expert&lt;/td&gt;
        &lt;td&gt;Saves the workspace with a specific version number so that it can be build upon in the future.&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
        &lt;td&gt;Engineer&lt;/td&gt;
        &lt;td&gt;Reviews the technical portion of the generated System Design document so that one can understand more about the business domain.&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
        &lt;td&gt;Engineer&lt;/td&gt;
        &lt;td&gt;Enters a prompt in Cucumber / Gherkin format to describe how the aggregates interact within the overall system so that the technical portion of the System Design can get updated automatically.&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
        &lt;td&gt;Engineer&lt;/td&gt;
        &lt;td&gt;Edits the technical portion of the generated System Design document so that more details can be manually added or corrected.&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
        &lt;td&gt;Engineer&lt;/td&gt;
        &lt;td&gt;Saves the workspace with a specific version number so that it can be build upon in the future.&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
        &lt;td&gt;Engineer&lt;/td&gt;
        &lt;td&gt;Initiates generation of deployment artifacts so that the system can be deployed in an out-of-band manner.&lt;/td&gt;
      &lt;/tr&gt;
    &lt;/tbody&gt;
  &lt;/table&gt;
&lt;/div&gt;
&lt;p&gt;The domain of the &lt;strong&gt;&lt;code&gt;Agentic DDD Platform&lt;/code&gt;&lt;/strong&gt; is as follows:&lt;/p&gt;
&lt;div class=&quot;simple-table-container&quot;&gt;
  &lt;table class=&quot;simple-table&quot;&gt;
    &lt;thead&gt;
      &lt;tr&gt;
        &lt;th&gt;Events&lt;/th&gt;
        &lt;th&gt;Objects&lt;/th&gt;
        &lt;th&gt;Transactions&lt;/th&gt;
      &lt;/tr&gt;
    &lt;/thead&gt;
    &lt;tbody&gt;
      &lt;tr&gt;
        &lt;td&gt;WorkspaceCreated&lt;/td&gt;
        &lt;td&gt;Workspace&lt;/td&gt;
        &lt;td&gt;CreateWorkspace&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
        &lt;td&gt;WorkspaceUpdated&lt;/td&gt;
        &lt;td&gt;&lt;/td&gt;
        &lt;td&gt;UpdateWorkspace&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
        &lt;td&gt;WorkspaceDeleted&lt;/td&gt;
        &lt;td&gt;&lt;/td&gt;
        &lt;td&gt;DeleteWorkspace&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
        &lt;td&gt;PromptSent&lt;/td&gt;
        &lt;td&gt;Prompt&lt;/td&gt;
        &lt;td&gt;SendPrompt&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
        &lt;td&gt;PromptResponse&lt;/td&gt;
        &lt;td&gt;&lt;/td&gt;
        &lt;td&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
        &lt;td&gt;DocumentCreated&lt;/td&gt;
        &lt;td&gt;Document&lt;/td&gt;
        &lt;td&gt;CreateDocument&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
        &lt;td&gt;DocumentEdited&lt;/td&gt;
        &lt;td&gt;&lt;/td&gt;
        &lt;td&gt;EditDocument&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
        &lt;td&gt;UserCreated&lt;/td&gt;
        &lt;td&gt;User&lt;/td&gt;
        &lt;td&gt;CreateUser&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
        &lt;td&gt;UserUpdated&lt;/td&gt;
        &lt;td&gt;&lt;/td&gt;
        &lt;td&gt;UpdateUser&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
        &lt;td&gt;UserDeleted&lt;/td&gt;
        &lt;td&gt;&lt;/td&gt;
        &lt;td&gt;DeleteUser&lt;/td&gt;
      &lt;/tr&gt;
    &lt;/tbody&gt;
  &lt;/table&gt;
&lt;/div&gt;
&lt;h4 id=&quot;ddd-tactical-design&quot;&gt;&lt;strong&gt;DDD Tactical Design&lt;/strong&gt;&lt;/h4&gt;
&lt;h5 id=&quot;collaboration-workflow&quot;&gt;Collaboration Workflow&lt;/h5&gt;
&lt;pre class=&quot;mermaid&quot;&gt;
sequenceDiagram
  actor user as Expert / Engineer / AI Agent
  participant docServer as Document Server
  participant Database@{ &quot;type&quot; : &quot;database&quot; }
  docServer-&gt;&gt;user: Server-Sent-Events connection
  user -&gt;&gt; docServer: POST: Updates document
  docServer --&gt;&gt; user: 200
  docServer -&gt;&gt; Database: Periodically saves document to DB
  Database --&gt;&gt; docServer: 200
&lt;/pre&gt;
&lt;h5 id=&quot;prompt-workflow&quot;&gt;Prompt Workflow&lt;/h5&gt;
&lt;pre class=&quot;mermaid&quot;&gt;
sequenceDiagram
  actor expert as Expert / Engineer
  participant promptServer as Prompt Server
  participant Database@{ &quot;type&quot; : &quot;database&quot; }
  participant agent as Agent
  participant llm as LLM Server
  participant docServer as Document Server
  expert-&gt;&gt;promptServer: POST: prompt&lt;br&gt;request
  promptServer-&gt;&gt;promptServer: Validate prompt
  promptServer-&gt;&gt;Database: insert prompt request
  Database--&gt;&gt;promptServer: success
  promptServer--&gt;&gt;expert: 200
  agent-&gt;&gt;Database: POLL: Read prompt request
  Database--&gt;&gt;agent: success
  loop till no more prompts
    agent-&gt;&gt;llm: Prompt the LLM
    llm--&gt;&gt;agent: LLM response
    alt new prompt
      agent-&gt;&gt;Database: insert prompt request
      Database--&gt;&gt;agent: success
    end
  end
  agent-&gt;&gt;Database: Create prompt response
  Database--&gt;&gt;agent: success
  agent-&gt;&gt;docServer: POST: Updates document
  docServer--&gt;&gt;agent: 200
  expert-&gt;&gt;promptServer: GET: prompt&lt;br&gt;response
  promptServer-&gt;&gt;Database: Read prompt response
  Database--&gt;&gt;promptServer: success
  promptServer--&gt;&gt;expert: 200
&lt;/pre&gt;
&lt;h5 id=&quot;artifact-generation-workflow&quot;&gt;Artifact Generation Workflow&lt;/h5&gt;
&lt;pre class=&quot;mermaid&quot;&gt;
sequenceDiagram
  actor engineer as Engineer
  participant artifactServer as Artifact Server
  participant Database@{ &quot;type&quot; : &quot;database&quot; }
  participant agent as Agent
  participant llm as LLM Server
  engineer-&gt;&gt;artifactServer: POST: Generate&lt;br&gt;Artifacts
  artifactServer-&gt;&gt;Database: insert GenerateArtifacts request
  Database--&gt;&gt;artifactServer: success
  agent-&gt;&gt;Database: POLL: Read GenerateArtifacts request
  Database--&gt;&gt;agent: success
  agent-&gt;&gt;Database: Read current Document state
  Database--&gt;&gt;agent: success
  agent-&gt;&gt;llm: Convert Document to structured JSONL
  llm--&gt;&gt;agent: JSONL responses
  loop till no more JSONL
    agent-&gt;&gt;agent: Generate Technical Artifact based on current JSONL
    agent-&gt;&gt;Database: Save Artifact into DB
    Database--&gt;&gt;agent: success
  end
  agent-&gt;&gt;Database: Create GenerateArtifacts response
  Database--&gt;&gt;agent: success
  engineer-&gt;&gt;artifactServer: GET: GenerateArtifacts&lt;br&gt;response
  artifactServer-&gt;&gt;Database: Read GenerateArtifacts response
  Database--&gt;&gt;artifactServer: success
  artifactServer-&gt;&gt;artifactServer: Compress Artifacts into a single object
  artifactServer--&gt;&gt;engineer: Compressed Artifacts download
&lt;/pre&gt;
&lt;h4 id=&quot;non-functional-requirements&quot;&gt;&lt;strong&gt;Non-Functional Requirements&lt;/strong&gt;&lt;/h4&gt;
&lt;p&gt;&lt;em&gt;TBD&lt;/em&gt;&lt;/p&gt;
&lt;h4 id=&quot;api-endpoints&quot;&gt;&lt;strong&gt;API Endpoints&lt;/strong&gt;&lt;/h4&gt;
&lt;p&gt;&lt;em&gt;TBD&lt;/em&gt;&lt;/p&gt;
&lt;h4 id=&quot;capacity-estimation&quot;&gt;&lt;strong&gt;Capacity Estimation&lt;/strong&gt;&lt;/h4&gt;
&lt;p&gt;&lt;em&gt;TBD&lt;/em&gt;&lt;/p&gt;
&lt;h4 id=&quot;cost-estimation&quot;&gt;&lt;strong&gt;Cost Estimation&lt;/strong&gt;&lt;/h4&gt;
&lt;p&gt;&lt;em&gt;TBD&lt;/em&gt;&lt;/p&gt;
&lt;h4 id=&quot;system-architecture&quot;&gt;&lt;strong&gt;System Architecture&lt;/strong&gt;&lt;/h4&gt;
&lt;p&gt;&lt;em&gt;TBD&lt;/em&gt;&lt;/p&gt;
&lt;hr&gt;

</content>
  </entry>
  <entry>
    <title>Context Engineering</title>
    <link href="https://sh4nnongoh.github.io/blog/10-context-engineering/" />
    <updated>2026-02-16T00:00:00Z</updated>
    <id>https://sh4nnongoh.github.io/blog/10-context-engineering/</id>
    <content type="html">&lt;p&gt;In the &lt;a href=&quot;https://sh4nnongoh.github.io/blog/9-ai-agents&quot;&gt;previous post&lt;/a&gt;, Ollama was setup locally and it can be queried upon through the &lt;a href=&quot;https://github.com/ollama/ollama/blob/main/docs/api.md&quot;&gt;HTTP API&lt;/a&gt;. The question now is how do we enhance the &lt;em&gt;LLM&lt;/em&gt; with tools such that it can help the users achieve what they want, &lt;strong&gt;without over-engineering&lt;/strong&gt; a solution.&lt;/p&gt;
&lt;div class=&quot;message-box&quot;&gt;
	&lt;p&gt;&lt;em&gt;
  IMPORTANT! DO NOT OVER-ENGINEER A SOLUTION!
  &lt;br&gt;&lt;br&gt;REPEAT AFTER ME.&lt;br&gt;&lt;br&gt;
  DO NOT OVER-ENGINEER A SOLUTION!
  &lt;/em&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;It is so easy to fall into the trap of over-engineering. If the &lt;em&gt;LLM&lt;/em&gt; does not respond correctly, excited engineers may just start writing &lt;em&gt;IF-ELSE&lt;/em&gt; statements to correct the answer. Do not get in the LLM way. If there is no straight forward path with a prompt and one level of depth of tools, just ask your scientist to give you a better model.&lt;/p&gt;
&lt;h2 id=&quot;start-simple&quot;&gt;Start Simple&lt;/h2&gt;
&lt;p&gt;Let&#39;s start with a simple scenario.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Prompt: What is 1+1?
Response:
{
  &amp;quot;model&amp;quot;: &amp;quot;qwen2.5-coder:3B&amp;quot;,
  &amp;quot;message&amp;quot;: {
    &amp;quot;role&amp;quot;: &amp;quot;assistant&amp;quot;,
    &amp;quot;content&amp;quot;: &amp;quot;{ &#92;&amp;quot;result&#92;&amp;quot;: &#92;&amp;quot;2&#92;&amp;quot; }&amp;quot;
  },
  // ...
}

Prompt: What is a LLM?
Response:
{
  &amp;quot;model&amp;quot;: &amp;quot;qwen2.5-coder:3B&amp;quot;,
  &amp;quot;message&amp;quot;: {
    &amp;quot;role&amp;quot;: &amp;quot;assistant&amp;quot;,
    &amp;quot;content&amp;quot;: &amp;quot;{ &#92;&amp;quot;answer&#92;&amp;quot;: &#92;&amp;quot;A Large Language Model (LLM) is an artificial intelligence model that can generate human-like text based on input data. It has been trained on vast amounts of text data and can understand, analyze, and generate language in various ways.&#92;&amp;quot; }&amp;quot;
  },
  // ...
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Asking 2 different simple questions, will result in totally 2 different responses with differing data structures. One stores the reply in a result field while the other stores it in the answer field. As an engineer, we need to deterministically retrieve the responses in a structured manner. Luckily there is the Format field we can pass in during the request.&lt;/p&gt;
&lt;h2 id=&quot;format-responses&quot;&gt;Format Responses&lt;/h2&gt;
&lt;pre class=&quot;language-go&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-go&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; OllamaResponseFormat &lt;span class=&quot;token keyword&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	Type       &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;                       &lt;span class=&quot;token string&quot;&gt;`json:&quot;type,omitempty&quot;`&lt;/span&gt;
	Properties &lt;span class=&quot;token keyword&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;`json:&quot;properties,omitempty&quot;`&lt;/span&gt;
	Required   &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;bool&lt;/span&gt;                       &lt;span class=&quot;token string&quot;&gt;`json:&quot;required,omitempty&quot;`&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;// Request Object&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;// ...&lt;/span&gt;
  OllamaResponseFormat&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    Type&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;       &lt;span class=&quot;token string&quot;&gt;&quot;object&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    Properties&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token string&quot;&gt;&quot;answer&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token string&quot;&gt;&quot;type&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;string&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;By setting the format before prompting, we can get structured responses as shown below, where all replies are within the answer field and it must be a string.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Prompt: What is 1+1?
Response:  {
  &amp;quot;model&amp;quot;: &amp;quot;qwen2.5-coder:3B&amp;quot;,
  &amp;quot;message&amp;quot;: {
    &amp;quot;role&amp;quot;: &amp;quot;assistant&amp;quot;,
    &amp;quot;content&amp;quot;: &amp;quot;{ &#92;&amp;quot;answer&#92;&amp;quot;: &#92;&amp;quot;2&#92;&amp;quot; }&amp;quot;
  },
  // ...
}

Prompt: What is a LLM?
Response:  {
  &amp;quot;model&amp;quot;: &amp;quot;qwen2.5-coder:3B&amp;quot;,
  &amp;quot;message&amp;quot;: {
    &amp;quot;role&amp;quot;: &amp;quot;assistant&amp;quot;,
    &amp;quot;content&amp;quot;: &amp;quot;{ &#92;&amp;quot;answer&#92;&amp;quot;: &#92;&amp;quot;A Large Language Model (LLM) is an artificial intelligence model that can generate human-like text based on input data. It has been trained on vast amounts of text data and can be used for various applications such as language translation, summarization, question answering, and more.&#92;&amp;quot; }&amp;quot;
  },
  // ...
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;supercharge-the-llm-with-tools&quot;&gt;Supercharge the LLM with Tools&lt;/h2&gt;
&lt;p&gt;As mentioned earlier we need to enhance the &lt;em&gt;LLM&lt;/em&gt; with tools such that it can do more than what it was trained to do.&lt;/p&gt;
&lt;div class=&quot;message-box&quot;&gt;
	&lt;p&gt;&lt;em&gt;
  NOTE: The LLM is just a brain that decides which tool to use. The actual computation needs to be written by the engineer. This is currently commonly done through the concept of Model Context Protocol (MCP) servers.
  &lt;/em&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;The structure of a Tool is shown below.&lt;/p&gt;
&lt;pre class=&quot;language-go&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-go&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; OllamaFunctionParameter &lt;span class=&quot;token keyword&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	Type       &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;          &lt;span class=&quot;token string&quot;&gt;`json:&quot;type&quot; description:&quot;Return type of the current function.&quot;`&lt;/span&gt;
	Required   &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;        &lt;span class=&quot;token string&quot;&gt;`json:&quot;required&quot; description:&quot;Which parameters are required in the function call.&quot;`&lt;/span&gt;
	Properties json&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;RawMessage &lt;span class=&quot;token string&quot;&gt;`json:&quot;properties&quot; description:&quot;Details about the parameters.&quot;`&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; OllamaFunction &lt;span class=&quot;token keyword&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	Name        &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;                  &lt;span class=&quot;token string&quot;&gt;`json:&quot;name&quot; description:&quot;Name of the Function.&quot;`&lt;/span&gt;
	Description &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;                  &lt;span class=&quot;token string&quot;&gt;`json:&quot;description&quot; description:&quot;What the Function does.&quot;`&lt;/span&gt;
	Parameters  OllamaFunctionParameter &lt;span class=&quot;token string&quot;&gt;`json:&quot;parameters&quot; description:&quot;Parameters that get passed to the Function.&quot;`&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; OllamaTool &lt;span class=&quot;token keyword&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	Type     &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;         &lt;span class=&quot;token string&quot;&gt;`json:&quot;type&quot; description:&quot;The type of Tool; i.e. Function&quot;`&lt;/span&gt;
	Function OllamaFunction &lt;span class=&quot;token string&quot;&gt;`json:&quot;function&quot; description:&quot;A Tool that is of Function type.&quot;`&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

tools &lt;span class=&quot;token operator&quot;&gt;:=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;OllamaTool&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
		Type&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;function&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
		Function&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; OllamaFunction&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
			Name&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;        &lt;span class=&quot;token string&quot;&gt;&quot;GetWeatherTemperature&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
			Description&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Get the Temperature.&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
			Parameters&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;  OllamaFunctionParameter&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
		&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
		Type&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;function&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
		Function&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; OllamaFunction&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
			Name&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;        &lt;span class=&quot;token string&quot;&gt;&quot;GetTime&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
			Description&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Get the Time.&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
			Parameters&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;  OllamaFunctionParameter&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
		&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
		Type&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;function&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
		Function&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; OllamaFunction&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
			Name&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;        &lt;span class=&quot;token string&quot;&gt;&quot;GetLLMDefinition&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
			Description&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Get the LLM definition.&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
			Parameters&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;  OllamaFunctionParameter&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
		&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Let&#39;s ask the &lt;em&gt;LLM&lt;/em&gt;, what the weather is.&lt;/p&gt;
&lt;p&gt;When querying with the Tools defined, the response is as follows:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Prompt: What is the Weather now?
Tools: &amp;lt;tools&amp;gt;
Response: {
  &amp;quot;model&amp;quot;: &amp;quot;qwen2.5-coder:3B&amp;quot;,
  &amp;quot;message&amp;quot;: {
    &amp;quot;role&amp;quot;: &amp;quot;assistant&amp;quot;,
    &amp;quot;content&amp;quot;: &amp;quot;{&#92;&amp;quot;answer&#92;&amp;quot;:&#92;&amp;quot;GetWeatherTemperature&#92;&amp;quot;}&amp;quot;
  },
  // ...
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We can then Prompt again with the Tool result as follows:&lt;/p&gt;
&lt;pre class=&quot;language-go&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-go&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; OllamaMessage &lt;span class=&quot;token keyword&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	Role    &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;`json:&quot;role&quot; description:&quot;Who is requesting the message.&quot;`&lt;/span&gt;
	Content &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;`json:&quot;content&quot; description:&quot;The actual message content.&quot;`&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;// Request Object&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;// ...&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;OllamaMessage&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    Role&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;    &lt;span class=&quot;token string&quot;&gt;&quot;user&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    Content&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;What is the Weather now?&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    Role&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;    &lt;span class=&quot;token string&quot;&gt;&quot;assistant&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    Content&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;{&#92;&quot;answer&#92;&quot;: &#92;&quot;GetWeatherTemperature&#92;&quot;}&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    Role&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;tool&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    Content&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;11 degrees celsius&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The second Prompt request includes the conversation history along with the Tool call and its result.&lt;/p&gt;
&lt;p&gt;The response can be seen below.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Response:  {
  &amp;quot;model&amp;quot;: &amp;quot;qwen2.5-coder:3B&amp;quot;,
  &amp;quot;message&amp;quot;: {
    &amp;quot;role&amp;quot;: &amp;quot;assistant&amp;quot;,
    &amp;quot;content&amp;quot;: &amp;quot;{&#92;&amp;quot;answer&#92;&amp;quot;: &#92;&amp;quot;The current temperature is 11 degrees Celsius.&#92;&amp;quot;}&amp;quot;
  },
  // ...
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;hallucination&quot;&gt;Hallucination&lt;/h2&gt;
&lt;pre&gt;&lt;code&gt;Prompt: What is the time now?
Tools: &amp;lt;tools&amp;gt;
Response: {
  &amp;quot;model&amp;quot;: &amp;quot;qwen2.5-coder:3B&amp;quot;,
  &amp;quot;message&amp;quot;: {
    &amp;quot;role&amp;quot;: &amp;quot;assistant&amp;quot;,
    &amp;quot;content&amp;quot;: &amp;quot;{&#92;&amp;quot;answer&#92;&amp;quot;:&#92;&amp;quot;1683240000&#92;&#92;&amp;quot;}&amp;quot;
  },
  // ...
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;When querying with the Prompt above, the &lt;em&gt;LLM&lt;/em&gt; assumes that it knows the answer, but it is clearly wrong.&lt;/p&gt;
&lt;p&gt;Because we expect an &lt;em&gt;&#39;answer&#39;&lt;/em&gt; as defined in Format options, the &lt;em&gt;LLM&lt;/em&gt; responds with what it assumes is the current time.&lt;/p&gt;
&lt;pre class=&quot;language-go&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-go&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// Request Object&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;// ...&lt;/span&gt;
  OllamaResponseFormat&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    Type&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;       &lt;span class=&quot;token string&quot;&gt;&quot;object&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    Properties&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token string&quot;&gt;&quot;answer&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token string&quot;&gt;&quot;type&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;string&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token string&quot;&gt;&quot;function_call&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token string&quot;&gt;&quot;type&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;string&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;By adding a new field &lt;em&gt;function_call&lt;/em&gt; to the Format options, we allow the &lt;em&gt;LLM&lt;/em&gt; to make a choice to call a Tool.&lt;/p&gt;
&lt;p&gt;The response is as follows:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Response: {
  &amp;quot;model&amp;quot;: &amp;quot;qwen2.5-coder:3B&amp;quot;,
  &amp;quot;message&amp;quot;: {
    &amp;quot;role&amp;quot;: &amp;quot;assistant&amp;quot;,
    &amp;quot;content&amp;quot;: &amp;quot;{&#92;&amp;quot;function_call&#92;&amp;quot;: &#92;&amp;quot;GetTime&#92;&amp;quot;}&amp;quot;
  },
  // ...
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We can see that the &lt;em&gt;LLM&lt;/em&gt; now uses the Tool to get the time.&lt;/p&gt;
&lt;h2 id=&quot;testing-the-changes-with-other-prompts&quot;&gt;Testing the changes with other Prompts&lt;/h2&gt;
&lt;p&gt;Let&#39;s ask the &lt;em&gt;1+1&lt;/em&gt; question again.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Prompt: What is 1+1?
Tools: &amp;lt;tools&amp;gt;
Response: {
  &amp;quot;model&amp;quot;: &amp;quot;qwen2.5-coder:3B&amp;quot;,
  &amp;quot;message&amp;quot;: {
    &amp;quot;role&amp;quot;: &amp;quot;assistant&amp;quot;,
    &amp;quot;content&amp;quot;: &amp;quot;{&#92;&amp;quot;function_call&#92;&amp;quot;:&#92;&amp;quot;GetLLMDefinition&#92;&#92;&#92;&amp;quot;}&amp;quot;
  },
  // ...
}
&lt;/code&gt;&lt;/pre&gt;
&lt;div class=&quot;message-box&quot;&gt;
	&lt;p&gt;&lt;em&gt;
  What... Why is it asking for LLM definition??? Is it just a lousy model? Is it bad prompting? Can&#39;t be... This is such a simple scenario. Honestly, who knows? The LLM is a black box! MOVING ON!
  &lt;/em&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;If we remove all the Tools from the Prompt request, then it can respond with the answer &lt;em&gt;&amp;quot;2&amp;quot;&lt;/em&gt;.&lt;/p&gt;
&lt;h2 id=&quot;dynamic-contexts&quot;&gt;Dynamic Contexts&lt;/h2&gt;
&lt;p&gt;We need a way to dynamically inject tools to the Prompt request. However, remember that we &lt;strong&gt;DO NOT WANT&lt;/strong&gt; to over-engineer a solution.&lt;/p&gt;
&lt;p&gt;Let&#39;s ask the LLM to do it for us.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;System Prompt:
Tools available:
- GetWeatherTemperature: Get the current temperature.
- GetTime: Get the current time.
- GetLLMDefinition: Get the definition of a LLM.

Prompt:
What tool is needed to answer the question &amp;quot;What is 1+1?&amp;quot;
You may return empty string if no suitable tool is available.

Response: {
  &amp;quot;model&amp;quot;: &amp;quot;qwen2.5-coder:3B&amp;quot;,
  &amp;quot;message&amp;quot;: {
    &amp;quot;role&amp;quot;: &amp;quot;assistant&amp;quot;,
    &amp;quot;content&amp;quot;: &amp;quot;{&#92;&amp;quot;function_call&#92;&amp;quot;:&#92;&amp;quot;&#92;&#92;&#92;&amp;quot;}&amp;quot;
  },
  // ...
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;After defining the Tools available in the System Prompt, we ask the &lt;em&gt;LLM&lt;/em&gt; to setup which Tools we should use for our Prompt. In this scenario, none of the Tools are compatible to answer the question &lt;em&gt;&amp;quot;What is 1+1?&amp;quot;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Now we can programmatically know to not send the Tools with the Prompt, allowing the &lt;em&gt;LLM&lt;/em&gt; to derive the answer.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Prompt: What is 1+1?
Tools: nil
Response:  {
  &amp;quot;model&amp;quot;: &amp;quot;qwen2.5-coder:3B&amp;quot;,
  &amp;quot;message&amp;quot;: {
    &amp;quot;role&amp;quot;: &amp;quot;assistant&amp;quot;,
    &amp;quot;content&amp;quot;: &amp;quot;{ &#92;&amp;quot;answer&#92;&amp;quot;: &#92;&amp;quot;2&#92;&amp;quot; }&amp;quot;
  },
  // ...
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Start simple with the goal of defining the structure of the responses.&lt;/li&gt;
&lt;li&gt;Iterate across sample prompts, to catch edge cases.&lt;/li&gt;
&lt;li&gt;Establish 2-stage prompting, whereby the &lt;em&gt;LLM&lt;/em&gt; first decides what &lt;em&gt;Tools&lt;/em&gt; to use, followed by fulfilling the actual prompt made by the user using the insight gained on the compatibility of &lt;em&gt;Tools&lt;/em&gt; available in the first prompt.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;By following the above methodology, I believe an &lt;em&gt;&amp;quot;AI Engineer&amp;quot;&lt;/em&gt; may find more success in achieving business objectives!&lt;/p&gt;
&lt;h2 id=&quot;appendix-data-structures-for-ollama&quot;&gt;Appendix (Data Structures for Ollama)&lt;/h2&gt;
&lt;pre class=&quot;language-go&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-go&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; OllamaMessage &lt;span class=&quot;token keyword&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  Role    &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;`json:&quot;role&quot; description:&quot;Who is requesting the message.&quot;`&lt;/span&gt;
  Content &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;`json:&quot;content&quot; description:&quot;The actual message content.&quot;`&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; OllamaFunctionParameter &lt;span class=&quot;token keyword&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  Type       &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;          &lt;span class=&quot;token string&quot;&gt;`json:&quot;type&quot; description:&quot;Return type of the current function.&quot;`&lt;/span&gt;
  Required   &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;        &lt;span class=&quot;token string&quot;&gt;`json:&quot;required&quot; description:&quot;Which parameters are required in the function call.&quot;`&lt;/span&gt;
  Properties json&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;RawMessage &lt;span class=&quot;token string&quot;&gt;`json:&quot;properties&quot; description:&quot;Details about the parameters.&quot;`&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; OllamaFunction &lt;span class=&quot;token keyword&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  Name        &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;                  &lt;span class=&quot;token string&quot;&gt;`json:&quot;name&quot; description:&quot;Name of the Function.&quot;`&lt;/span&gt;
  Description &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;                  &lt;span class=&quot;token string&quot;&gt;`json:&quot;description&quot; description:&quot;What the Function does.&quot;`&lt;/span&gt;
  Parameters  OllamaFunctionParameter &lt;span class=&quot;token string&quot;&gt;`json:&quot;parameters&quot; description:&quot;Parameters that get passed to the Function.&quot;`&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; OllamaTool &lt;span class=&quot;token keyword&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  Type     &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;         &lt;span class=&quot;token string&quot;&gt;`json:&quot;type&quot; description:&quot;The type of Tool; i.e. Function&quot;`&lt;/span&gt;
  Function OllamaFunction &lt;span class=&quot;token string&quot;&gt;`json:&quot;function&quot; description:&quot;A Tool that is of Function type.&quot;`&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// ModelOptions defines common model parameters for the Options field&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; ModelOptions &lt;span class=&quot;token keyword&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;// Temperature controls randomness (0.0 to 1.0)&lt;/span&gt;
  Temperature &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;float64&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;`json:&quot;temperature,omitempty&quot;`&lt;/span&gt;

  &lt;span class=&quot;token comment&quot;&gt;// TopP controls diversity via nucleus sampling (0.0 to 1.0)&lt;/span&gt;
  TopP &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;float64&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;`json:&quot;top_p,omitempty&quot;`&lt;/span&gt;

  &lt;span class=&quot;token comment&quot;&gt;// TopK limits token selection to top K&lt;/span&gt;
  TopK &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;`json:&quot;top_k,omitempty&quot;`&lt;/span&gt;

  &lt;span class=&quot;token comment&quot;&gt;// NumPredict sets maximum number of tokens to predict&lt;/span&gt;
  NumPredict &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;`json:&quot;num_predict,omitempty&quot;`&lt;/span&gt;

  &lt;span class=&quot;token comment&quot;&gt;// RepeatPenalty penalizes repetition (1.0 = no penalty)&lt;/span&gt;
  RepeatPenalty &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;float64&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;`json:&quot;repeat_penalty,omitempty&quot;`&lt;/span&gt;

  &lt;span class=&quot;token comment&quot;&gt;// PresencePenalty penalizes new tokens based on presence&lt;/span&gt;
  PresencePenalty &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;float64&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;`json:&quot;presence_penalty,omitempty&quot;`&lt;/span&gt;

  &lt;span class=&quot;token comment&quot;&gt;// FrequencyPenalty penalizes new tokens based on frequency&lt;/span&gt;
  FrequencyPenalty &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;float64&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;`json:&quot;frequency_penalty,omitempty&quot;`&lt;/span&gt;

  &lt;span class=&quot;token comment&quot;&gt;// Mirostat enables mirostat sampling&lt;/span&gt;
  Mirostat &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;`json:&quot;mirostat,omitempty&quot;`&lt;/span&gt;

  &lt;span class=&quot;token comment&quot;&gt;// MirostatTau sets target entropy for mirostat&lt;/span&gt;
  MirostatTau &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;float64&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;`json:&quot;mirostat_tau,omitempty&quot;`&lt;/span&gt;

  &lt;span class=&quot;token comment&quot;&gt;// MirostatEta sets learning rate for mirostat&lt;/span&gt;
  MirostatEta &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;float64&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;`json:&quot;mirostat_eta,omitempty&quot;`&lt;/span&gt;

  &lt;span class=&quot;token comment&quot;&gt;// Stop sets custom stop sequences&lt;/span&gt;
  Stop &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;`json:&quot;stop,omitempty&quot;`&lt;/span&gt;

  &lt;span class=&quot;token comment&quot;&gt;// Seed sets random seed for reproducibility&lt;/span&gt;
  Seed &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;`json:&quot;seed,omitempty&quot;`&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; OllamaResponseFormat &lt;span class=&quot;token keyword&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  Type       &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;                       &lt;span class=&quot;token string&quot;&gt;`json:&quot;type,omitempty&quot;`&lt;/span&gt;
  Properties &lt;span class=&quot;token keyword&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;`json:&quot;properties,omitempty&quot;`&lt;/span&gt;
  Required   &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;bool&lt;/span&gt;                       &lt;span class=&quot;token string&quot;&gt;`json:&quot;required,omitempty&quot;`&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; OllamaRequest &lt;span class=&quot;token keyword&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  Model &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;       &lt;span class=&quot;token string&quot;&gt;`json:&quot;model&quot; description:&quot;LLM model to be used.&quot;`&lt;/span&gt;
  Tools &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;OllamaTool &lt;span class=&quot;token string&quot;&gt;`json:&quot;tools&quot; description:&quot;List of Tools the LLM can use.&quot;`&lt;/span&gt;

  &lt;span class=&quot;token comment&quot;&gt;// Depending on the model, either field is used&lt;/span&gt;
  Messages &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;OllamaMessage &lt;span class=&quot;token string&quot;&gt;`json:&quot;messages,omitempty&quot; description:&quot;List of messages in the current prompt.&quot;`&lt;/span&gt;
  Prompt   &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;          &lt;span class=&quot;token string&quot;&gt;`json:&quot;prompt,omitempty&quot;`&lt;/span&gt;

  &lt;span class=&quot;token comment&quot;&gt;// Optional fields&lt;/span&gt;
  Suffix    &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;               &lt;span class=&quot;token string&quot;&gt;`json:&quot;suffix,omitempty&quot;`&lt;/span&gt;
  Images    &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;             &lt;span class=&quot;token string&quot;&gt;`json:&quot;images,omitempty&quot;`&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// base64-encoded images&lt;/span&gt;
  Format    OllamaResponseFormat &lt;span class=&quot;token string&quot;&gt;`json:&quot;format,omitempty&quot;`&lt;/span&gt;
  Options   ModelOptions         &lt;span class=&quot;token string&quot;&gt;`json:&quot;options,omitempty&quot;`&lt;/span&gt;
  System    &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;               &lt;span class=&quot;token string&quot;&gt;`json:&quot;system,omitempty&quot;`&lt;/span&gt;
  Template  &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;               &lt;span class=&quot;token string&quot;&gt;`json:&quot;template,omitempty&quot;`&lt;/span&gt;
  Stream    &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;bool&lt;/span&gt;                &lt;span class=&quot;token string&quot;&gt;`json:&quot;stream,omitempty&quot; description:&quot;To stream the response or not.&quot;`&lt;/span&gt;
  Raw       &lt;span class=&quot;token builtin&quot;&gt;bool&lt;/span&gt;                 &lt;span class=&quot;token string&quot;&gt;`json:&quot;raw,omitempty&quot;`&lt;/span&gt;
  KeepAlive &lt;span class=&quot;token builtin&quot;&gt;int&lt;/span&gt;                  &lt;span class=&quot;token string&quot;&gt;`json:&quot;keep_alive,omitempty&quot;`&lt;/span&gt;

  &lt;span class=&quot;token comment&quot;&gt;// Experimental image generation fields&lt;/span&gt;
  Width  &lt;span class=&quot;token builtin&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;`json:&quot;width,omitempty&quot;`&lt;/span&gt;
  Height &lt;span class=&quot;token builtin&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;`json:&quot;height,omitempty&quot;`&lt;/span&gt;
  Steps  &lt;span class=&quot;token builtin&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;`json:&quot;steps,omitempty&quot;`&lt;/span&gt;

  &lt;span class=&quot;token comment&quot;&gt;// Thinking models parameter&lt;/span&gt;
  Think &lt;span class=&quot;token builtin&quot;&gt;bool&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;`json:&quot;think,omitempty&quot;`&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; OllamaResponse &lt;span class=&quot;token keyword&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  Model     &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;        &lt;span class=&quot;token string&quot;&gt;`json:&quot;model&quot; description:&quot;LLM model to be used.&quot;`&lt;/span&gt;
  Message   OllamaMessage &lt;span class=&quot;token string&quot;&gt;`json:&quot;message&quot; description:&quot;List of messages in the current prompt.&quot;`&lt;/span&gt;
  Response  &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;        &lt;span class=&quot;token string&quot;&gt;`json:&quot;response&quot;`&lt;/span&gt;
  Done      &lt;span class=&quot;token builtin&quot;&gt;bool&lt;/span&gt;          &lt;span class=&quot;token string&quot;&gt;`json:&quot;done&quot; description:&quot;Response is done streaming.&quot;`&lt;/span&gt;
  CreatedAt time&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Time     &lt;span class=&quot;token string&quot;&gt;`json:&quot;created_at&quot; description:&quot;Timestamp when response was created.&quot;`&lt;/span&gt;

  &lt;span class=&quot;token comment&quot;&gt;// Additional fields present only when Done = true&lt;/span&gt;
  Context            &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;int&lt;/span&gt;  &lt;span class=&quot;token string&quot;&gt;`json:&quot;context,omitempty&quot;`&lt;/span&gt;
  TotalDuration      &lt;span class=&quot;token builtin&quot;&gt;int64&lt;/span&gt;  &lt;span class=&quot;token string&quot;&gt;`json:&quot;total_duration,omitempty&quot;`&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// nanoseconds&lt;/span&gt;
  LoadDuration       &lt;span class=&quot;token builtin&quot;&gt;int64&lt;/span&gt;  &lt;span class=&quot;token string&quot;&gt;`json:&quot;load_duration,omitempty&quot;`&lt;/span&gt;  &lt;span class=&quot;token comment&quot;&gt;// nanoseconds&lt;/span&gt;
  PromptEvalCount    &lt;span class=&quot;token builtin&quot;&gt;int&lt;/span&gt;    &lt;span class=&quot;token string&quot;&gt;`json:&quot;prompt_eval_count,omitempty&quot;`&lt;/span&gt;
  PromptEvalDuration &lt;span class=&quot;token builtin&quot;&gt;int64&lt;/span&gt;  &lt;span class=&quot;token string&quot;&gt;`json:&quot;prompt_eval_duration,omitempty&quot;`&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// nanoseconds&lt;/span&gt;
  EvalCount          &lt;span class=&quot;token builtin&quot;&gt;int&lt;/span&gt;    &lt;span class=&quot;token string&quot;&gt;`json:&quot;eval_count,omitempty&quot;`&lt;/span&gt;
  EvalDuration       &lt;span class=&quot;token builtin&quot;&gt;int64&lt;/span&gt;  &lt;span class=&quot;token string&quot;&gt;`json:&quot;eval_duration,omitempty&quot;`&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// nanoseconds&lt;/span&gt;
  DoneReason         &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;`json:&quot;done_reason,omitempty&quot;`&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; AnyFunc &lt;span class=&quot;token keyword&quot;&gt;func&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;interface&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;interface&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

</content>
  </entry>
  <entry>
    <title>AI Agents</title>
    <link href="https://sh4nnongoh.github.io/blog/9-ai-agents/" />
    <updated>2026-02-08T00:00:00Z</updated>
    <id>https://sh4nnongoh.github.io/blog/9-ai-agents/</id>
    <content type="html">&lt;br&gt;
&lt;br&gt;
&lt;div class=&quot;message-box&quot;&gt;
	&lt;p&gt;&lt;em&gt;Disclaimer: I am not an &quot;AI Engineer&quot; or whatever that means. This post describes my thoughts and reflections on the current landscape at this current point in time, and may very well change in the future.&lt;/em&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;br&gt;
&lt;picture&gt;&lt;source type=&quot;image/avif&quot; srcset=&quot;https://sh4nnongoh.github.io/blog/9-ai-agents/AlYejncQqb-1416.avif 1416w&quot;&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://sh4nnongoh.github.io/blog/9-ai-agents/AlYejncQqb-1416.webp 1416w&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; src=&quot;https://sh4nnongoh.github.io/blog/9-ai-agents/AlYejncQqb-1416.png&quot; alt=&quot;rag&quot; width=&quot;1416&quot; height=&quot;1974&quot;&gt;&lt;/picture&gt;
&lt;p align=&quot;center&quot;&gt;&lt;em&gt;RAG&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;I was scrolling &lt;strong&gt;X&lt;/strong&gt; one day and saw this &lt;a href=&quot;https://x.com/goyalshaliniuk/status/2019735325321388416?s=20&quot;&gt;post&lt;/a&gt; about RAG. I thought &lt;em&gt;&amp;quot;Whoa! The AI landscape has evolved so much!&amp;quot;&lt;/em&gt;. So I started going down the rabbit hole, trying to understand what RAG is.&lt;/p&gt;
&lt;div class=&quot;message-box&quot;&gt;
	&lt;p&gt;&lt;em&gt;Retrieval-augmented generation (RAG) is a technique that enhances large language models (LLMs) by allowing them to retrieve and incorporate new information from external data sources before generating responses. This approach improves the accuracy and relevance of the information provided by the LLMs.&lt;br&gt;- Wikipedia&lt;/em&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;So apparently this is a &lt;strong&gt;&lt;em&gt;technique&lt;/em&gt;&lt;/strong&gt; used to interface with an LLM? Okay, what exactly is this technique I wondered. So I went to setup my own LLM, and since I have a MacBook, I went with the Ollama setup.&lt;/p&gt;
&lt;picture&gt;&lt;source type=&quot;image/avif&quot; srcset=&quot;https://sh4nnongoh.github.io/blog/9-ai-agents/2O4E1VpKRL-1974.avif 1974w&quot;&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://sh4nnongoh.github.io/blog/9-ai-agents/2O4E1VpKRL-1974.webp 1974w&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; src=&quot;https://sh4nnongoh.github.io/blog/9-ai-agents/2O4E1VpKRL-1974.png&quot; alt=&quot;ollama&quot; width=&quot;1974&quot; height=&quot;694&quot;&gt;&lt;/picture&gt;
&lt;p align=&quot;center&quot;&gt;&lt;em&gt;Ollama&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Looking at the &lt;a href=&quot;https://docs.ollama.com/quickstart#curl&quot;&gt;docs&lt;/a&gt;, Ollama exposes a HTTP endpoint where we can send HTTP request to interface with the model.&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;curl&lt;/span&gt; http://localhost:11434/api/chat &lt;span class=&quot;token parameter variable&quot;&gt;-d&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;{
  &quot;model&quot;: &quot;qwen2.5-coder:3B&quot;,
  &quot;messages&quot;: [{
    &quot;role&quot;: &quot;user&quot;,
    &quot;content&quot;: &quot;What are you?&quot;
  }],
  &quot;stream&quot;: false
}&#39;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;There is this concept of Tools as well, which we can prompt the LLM to use.&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;curl&lt;/span&gt; http://localhost:11434/api/chat &lt;span class=&quot;token parameter variable&quot;&gt;-d&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;{
  &quot;model&quot;: &quot;qwen2.5-coder:3B&quot;,
  &quot;messages&quot;: [{
    &quot;role&quot;: &quot;user&quot;,
    &quot;content&quot;: &quot;What are you?&quot;
  }],
  &quot;stream&quot;: false,
  &quot;tools&quot;: [
    &quot;type&quot;: &quot;function&quot;,
    &quot;function&quot;: {
      &quot;name&quot;: &quot;ask_god&quot;,
      &quot;description&quot;: &quot;Prays to God for an answer.&quot;,
      &quot;parameters&quot;: {
        &quot;type&quot;: &quot;object&quot;,
        &quot;required&quot;: [&quot;god_name&quot;],
        &quot;properties&quot;: {
          &quot;god_name&quot;: {
            &quot;type&quot;: &quot;string&quot;,
            &quot;description&quot;: &quot;The name of the God you wish to pray to.&quot;
          }
        },
      },
    }
  ]
}&#39;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If the LLM does not know the answer, the response will request the use of Tools available. The engineer will then have to write code to call the specific tool and pipe the response back to the LLM. An example is shown below.&lt;/p&gt;
&lt;pre class=&quot;language-json&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// Initial Response&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;model&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;qwen2.5-coder:3B&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;message&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;role&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;assistant&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;content&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;{&#92;&quot;name&#92;&quot;: &#92;&quot;ask_god Prays to God for an answer.&#92;&quot;, &#92;&quot;arguments&#92;&quot;: {&#92;&quot;god_name&#92;&quot;: &#92;&quot;Some God&#92;&quot;}}&quot;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;//...&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;// Reply with Tool answer&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;//...&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token property&quot;&gt;&quot;role&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;tool&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token property&quot;&gt;&quot;tool_name&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;ask_god&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token property&quot;&gt;&quot;content&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;I am GOD!&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;So apparently this &lt;strong&gt;&lt;em&gt;technique&lt;/em&gt;&lt;/strong&gt; is just a mechanism for piping &lt;em&gt;JSON&lt;/em&gt; object messages back-and-forth between an engineer&#39;s code and the LLM. Why is there a need to create so many complicated fancy names for this back-and-forth messaging?&lt;/p&gt;
&lt;h2 id=&quot;engineers-vs-scientists&quot;&gt;Engineers VS Scientists&lt;/h2&gt;
&lt;p&gt;From an engineer&#39;s point-of-view, we only care about improving production metrics.&lt;/p&gt;
&lt;p&gt;When developing a feature, the first question we ask ourselves is that is it working or is it correct. When relying on an LLM system, the correctness largely depends on the LLM component as it is probabilistic in nature. It is not the job of an engineer to solve accuracy issues but that of a data scientist. But hey, RAG exists so that engineers can direct the LLM to find a correct answer right? NO! I strongly believe that is the wrong thought process to have as one would end up over-engineering a solution to the problem. If one cares about complete correctness, an engineer should not rely on a probabilistic engine but code out the exact requirements needed for the problem.&lt;/p&gt;
&lt;p&gt;Okay so we accept that it may not be accurate but it can still provide good summaries of information and possibly be a good assistant. Using ChatGPT, DeepSeek, Grok, etc. is great for querying or generating information and content. So why do we not just embed these models into our applications? The answer is cost; it is expensive to host and maintain such a large model while scaling it to many clients.&lt;/p&gt;
&lt;div class=&quot;message-box&quot;&gt;
	&lt;p&gt;&lt;em&gt;The value comes from choosing a small model to keep cost low, and making it work for a particular business use-case; possibly using RAG.&lt;/em&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;The engineer can monitor the number of tokens consumed by the model, along with the end-to-end latency of request(s), when attempting to &lt;em&gt;&amp;quot;solve&amp;quot;&lt;/em&gt; a business problem. The results can be benchmarked with the latest state-of-the-art models in terms of accuracy, with the goal of reducing the metrics mentioned above as much as possible to keep cost low.&lt;/p&gt;
&lt;p&gt;My future posts will dive deeper into such problems, and attempt to define what an &lt;em&gt;&amp;quot;AI Engineer&amp;quot;&lt;/em&gt; actually is.&lt;/p&gt;
&lt;div class=&quot;message-box&quot;&gt;
	&lt;p&gt;&lt;em&gt;Fun Fact: The So-So-Ah-So post tag is just to state that the current post is a reflection post. So-So-Ah-So is a Singapore singlish way of talking, whereby our sentences continuously have the word &quot;so&quot; to prove a point.&lt;/em&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;br&gt;
</content>
  </entry>
  <entry>
    <title>pprof CPU</title>
    <link href="https://sh4nnongoh.github.io/blog/8-pprof-cpu/" />
    <updated>2026-02-03T00:00:00Z</updated>
    <id>https://sh4nnongoh.github.io/blog/8-pprof-cpu/</id>
    <content type="html">&lt;br&gt;
&lt;br&gt;
&lt;div class=&quot;message-box&quot;&gt;
	&lt;p&gt;&lt;em&gt;This is &lt;strong&gt;Part 7&lt;/strong&gt; of the Magic Link System Design Series.&lt;/em&gt;&lt;/p&gt;
  &lt;ol&gt;
    &lt;li&gt;&lt;a href=&quot;https://sh4nnongoh.github.io/blog/2-system-design&quot;&gt;System Design&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&quot;https://sh4nnongoh.github.io/blog/3-magic-links&quot;&gt;Magic Links&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&quot;https://sh4nnongoh.github.io/blog/4-csrf-magic-links&quot;&gt;CSRF with Magic Links&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&quot;https://sh4nnongoh.github.io/blog/5-pprof&quot;&gt;pprof &amp; Load Testing&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&quot;https://sh4nnongoh.github.io/blog/6-pprof-analysis&quot;&gt;pprof Analysis&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&quot;https://sh4nnongoh.github.io/blog/7-pprof-mem&quot;&gt;pprof Memory Optimizations&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;pprof CPU&lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;
&lt;br&gt;
&lt;picture&gt;&lt;source type=&quot;image/avif&quot; srcset=&quot;https://sh4nnongoh.github.io/blog/8-pprof-cpu/OJ6v8qIjj8-3416.avif 3416w&quot;&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://sh4nnongoh.github.io/blog/8-pprof-cpu/OJ6v8qIjj8-3416.webp 3416w&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; src=&quot;https://sh4nnongoh.github.io/blog/8-pprof-cpu/OJ6v8qIjj8-3416.png&quot; alt=&quot;cpu-base&quot; width=&quot;3416&quot; height=&quot;1662&quot;&gt;&lt;/picture&gt;
&lt;p align=&quot;center&quot;&gt;&lt;em&gt;CPU&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;The above CPU flamegraph shows the CPU utilization after the memory optimizations made in the &lt;a href=&quot;https://sh4nnongoh.github.io/blog/7-pprof-mem/&quot;&gt;previous post&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;As seen in the flamegraph, the &lt;em&gt;Magic Link&lt;/em&gt; handler takes up less than half of the CPU utilization during the sample period. This is expected as it is a very simple handler. Majority of the compute in the handler is used for encryption, while the rest is part of the HTTP lifecycle.&lt;/p&gt;
&lt;p&gt;One area of optimization would be the &lt;em&gt;fmt.Fprint&lt;/em&gt; section that is part of the &lt;em&gt;Gin&lt;/em&gt; logger. Every request coming in will be logged synchronously, triggering &lt;em&gt;syscalls&lt;/em&gt; which consumes CPU utilization.&lt;/p&gt;
&lt;h2 id=&quot;benchmarks&quot;&gt;Benchmarks&lt;/h2&gt;
&lt;p&gt;When dealing with CPU utilization or latency, we need to gather baseline metrics of our system before making improvements, such that we can compare the results.&lt;/p&gt;
&lt;pre class=&quot;language-go&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-go&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// benchmark_test.go&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;package&lt;/span&gt; main

&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
	&lt;span class=&quot;token string&quot;&gt;&quot;net/http&quot;&lt;/span&gt;
	&lt;span class=&quot;token string&quot;&gt;&quot;net/http/httptest&quot;&lt;/span&gt;
	&lt;span class=&quot;token string&quot;&gt;&quot;testing&quot;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
	Host               &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;http://127.0.0.1:8080&quot;&lt;/span&gt;
	GenerateMagicRoute &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;/magic/generate&quot;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;BenchmarkGin&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;b &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;testing&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;B&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	router &lt;span class=&quot;token operator&quot;&gt;:=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;NewRouter&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
	req&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; err &lt;span class=&quot;token operator&quot;&gt;:=&lt;/span&gt; http&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;NewRequest&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;http&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;MethodPost&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; Host&lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt;GenerateMagicRoute&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;nil&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
	req&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Header&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Set&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;X-CSRF-Token&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;generateCsrf&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; err &lt;span class=&quot;token operator&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;nil&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
		b&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Error&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;err&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
		&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
	b&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;ResetTimer&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; b&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Loop&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
		w &lt;span class=&quot;token operator&quot;&gt;:=&lt;/span&gt; httptest&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;NewRecorder&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
		router&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;ServeHTTP&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;w&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; req&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The above code shows a simple benchmark test that is focus on the &lt;em&gt;Magic Link&lt;/em&gt; handler, with the results shown below.&lt;/p&gt;
&lt;picture&gt;&lt;source type=&quot;image/avif&quot; srcset=&quot;https://sh4nnongoh.github.io/blog/8-pprof-cpu/sqoRVDEKry-1398.avif 1398w&quot;&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://sh4nnongoh.github.io/blog/8-pprof-cpu/sqoRVDEKry-1398.webp 1398w&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; src=&quot;https://sh4nnongoh.github.io/blog/8-pprof-cpu/sqoRVDEKry-1398.png&quot; alt=&quot;benchmark-base&quot; width=&quot;1398&quot; height=&quot;196&quot;&gt;&lt;/picture&gt;
&lt;p align=&quot;center&quot;&gt;&lt;em&gt;Benchmark Results (baseline)&lt;/em&gt;&lt;/p&gt;
&lt;h3 id=&quot;metrics-legend&quot;&gt;Metrics Legend&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Symbol&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;op&lt;/td&gt;
&lt;td&gt;Operation&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ns&lt;/td&gt;
&lt;td&gt;Nano-seconds&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;allocs&lt;/td&gt;
&lt;td&gt;Number of Memory Allocations&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;B&lt;/td&gt;
&lt;td&gt;Bytes Allocated&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id=&quot;buffered-logging&quot;&gt;Buffered Logging&lt;/h2&gt;
&lt;p&gt;Writing logs to disk synchronously per request is slow. Unless your system is fragile, and you fear that logs go missing on your critical path, it makes sense to buffer the incoming logs before writing them to disk; grouping such calls reduce &lt;em&gt;syscalls&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;The logging library &lt;a href=&quot;https://github.com/uber-go/zap&quot;&gt;Zap&lt;/a&gt;, supports this and is the fastest so far among other libraries.&lt;/p&gt;
&lt;div class=&quot;message-box&quot;&gt;
	&lt;p&gt;
    &lt;em&gt;
      ...using &lt;strong&gt;encoding/json&lt;/strong&gt; and &lt;strong&gt;fmt.Fprintf&lt;/strong&gt; to log tons of &lt;strong&gt;interface{}&lt;/strong&gt; makes your application slow...
      &lt;br&gt;
      - https://github.com/uber-go/zap
    &lt;/em&gt;
  &lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;When replacing the default Gin logger, we need to add 2 middlewares: (1) Logging; (2) Recovery.&lt;/p&gt;
&lt;pre class=&quot;language-go&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-go&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;MiddlewareZapLogger&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;logger &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;zap&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Logger&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; gin&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;HandlerFunc &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;func&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;c &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;gin&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Context&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
		start &lt;span class=&quot;token operator&quot;&gt;:=&lt;/span&gt; time&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Now&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
		path &lt;span class=&quot;token operator&quot;&gt;:=&lt;/span&gt; c&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Request&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;URL&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Path
		raw &lt;span class=&quot;token operator&quot;&gt;:=&lt;/span&gt; c&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Request&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;URL&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;RawQuery
		&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; raw &lt;span class=&quot;token operator&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
			path &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; path &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;?&quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; raw
		&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

		c&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Next&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

		latency &lt;span class=&quot;token operator&quot;&gt;:=&lt;/span&gt; time&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Since&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;start&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

		logger&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Info&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;http request&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
			zap&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Int&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;status&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; c&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Writer&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Status&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
			zap&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;method&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; c&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Request&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Method&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
			zap&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;path&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; path&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
			zap&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;ip&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; c&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;ClientIP&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
			zap&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Duration&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;latency&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; latency&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
			zap&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;user_agent&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; c&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Request&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;UserAgent&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
			zap&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Int&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;bytes_out&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; c&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Writer&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Size&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
			zap&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;errors&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; c&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Errors&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;ByType&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;gin&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;ErrorTypePrivate&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
		&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;MiddlewareZapRecovery&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;logger &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;zap&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Logger&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; gin&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;HandlerFunc &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; gin&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;CustomRecovery&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;func&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;c &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;gin&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Context&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; recovered any&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
		logger&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Error&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;panic recovered&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
			zap&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Any&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;error&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; recovered&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
			zap&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;method&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; c&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Request&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Method&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
			zap&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;path&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; c&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Request&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;URL&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Path&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
		&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
		c&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;AbortWithStatus&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;http&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;StatusInternalServerError&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;// ...&lt;/span&gt;

  logger&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; err &lt;span class=&quot;token operator&quot;&gt;:=&lt;/span&gt; zap&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;NewProduction&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; err &lt;span class=&quot;token operator&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;nil&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
		&lt;span class=&quot;token boolean&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; fmt&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Errorf&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;failed to run router: %w&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; err&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
		&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;defer&lt;/span&gt; logger&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Sync&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  router &lt;span class=&quot;token operator&quot;&gt;:=&lt;/span&gt; gin&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;New&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
	router&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Use&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;MiddlewareZapLogger&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;logger&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
	router&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Use&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;MiddlewareZapRecovery&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;logger&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

  &lt;span class=&quot;token comment&quot;&gt;// ...&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Running the benchmarks again, we can see the optimized results below.&lt;/p&gt;
&lt;picture&gt;&lt;source type=&quot;image/avif&quot; srcset=&quot;https://sh4nnongoh.github.io/blog/8-pprof-cpu/E2HNG0_ydP-1398.avif 1398w&quot;&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://sh4nnongoh.github.io/blog/8-pprof-cpu/E2HNG0_ydP-1398.webp 1398w&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; src=&quot;https://sh4nnongoh.github.io/blog/8-pprof-cpu/E2HNG0_ydP-1398.png&quot; alt=&quot;benchmark-optimized&quot; width=&quot;1398&quot; height=&quot;196&quot;&gt;&lt;/picture&gt;
&lt;p align=&quot;center&quot;&gt;&lt;em&gt;Benchmark Results (Optimized)&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Using the &lt;em&gt;Zap&lt;/em&gt; logger, latency was improved by &lt;em&gt;(22614-5430) / 22614 = &lt;strong&gt;~76%&lt;/strong&gt;&lt;/em&gt;. This is a huge speed improvement!&lt;/p&gt;
&lt;picture&gt;&lt;source type=&quot;image/avif&quot; srcset=&quot;https://sh4nnongoh.github.io/blog/8-pprof-cpu/7FA5finAt3-3420.avif 3420w&quot;&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://sh4nnongoh.github.io/blog/8-pprof-cpu/7FA5finAt3-3420.webp 3420w&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; src=&quot;https://sh4nnongoh.github.io/blog/8-pprof-cpu/7FA5finAt3-3420.png&quot; alt=&quot;cpu-optimized&quot; width=&quot;3420&quot; height=&quot;1724&quot;&gt;&lt;/picture&gt;
&lt;p align=&quot;center&quot;&gt;&lt;em&gt;CPU (Optimized)&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Looking at the flamegraph, we can see that the &lt;em&gt;fmt.Fprint&lt;/em&gt; section is gone, and that the &lt;em&gt;syscalls&lt;/em&gt; are greatly reduced.&lt;/p&gt;
&lt;p&gt;The CPU utilization is still low as we can&#39;t increase the number of concurrent requests due to the RSS limit mentioned &lt;a href=&quot;https://sh4nnongoh.github.io/blog/6-pprof-analysis/#cpu&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;div class=&quot;message-box&quot;&gt;
	&lt;p&gt;
    &lt;em&gt;
      Check out the example project here!
      &lt;br&gt;
      &lt;a href=&quot;https://github.com/sh4nnongoh/go-csrf-magic-links/tree/cpu&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;
        https://github.com/sh4nnongoh/go-csrf-magic-links/tree/cpu
      &lt;/a&gt;
    &lt;/em&gt;
  &lt;/p&gt;
&lt;/div&gt;

</content>
  </entry>
  <entry>
    <title>pprof Memory Optimization</title>
    <link href="https://sh4nnongoh.github.io/blog/7-pprof-mem/" />
    <updated>2026-02-01T00:00:00Z</updated>
    <id>https://sh4nnongoh.github.io/blog/7-pprof-mem/</id>
    <content type="html">&lt;br&gt;
&lt;br&gt;
&lt;div class=&quot;message-box&quot;&gt;
	&lt;p&gt;&lt;em&gt;This is &lt;strong&gt;Part 6&lt;/strong&gt; of the Magic Link System Design Series.&lt;/em&gt;&lt;/p&gt;
  &lt;ol&gt;
    &lt;li&gt;&lt;a href=&quot;https://sh4nnongoh.github.io/blog/2-system-design&quot;&gt;System Design&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&quot;https://sh4nnongoh.github.io/blog/3-magic-links&quot;&gt;Magic Links&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&quot;https://sh4nnongoh.github.io/blog/4-csrf-magic-links&quot;&gt;CSRF with Magic Links&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&quot;https://sh4nnongoh.github.io/blog/5-pprof&quot;&gt;pprof &amp; Load Testing&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&quot;https://sh4nnongoh.github.io/blog/6-pprof-analysis&quot;&gt;pprof Analysis&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;pprof Memory Optimizations&lt;/li&gt;
    &lt;li&gt;&lt;a href=&quot;https://sh4nnongoh.github.io/blog/8-pprof-cpu&quot;&gt;pprof CPU&lt;/a&gt;&lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;
&lt;p&gt;In the &lt;a href=&quot;https://sh4nnongoh.github.io/blog/6-pprof-analysis/&quot;&gt;previous post&lt;/a&gt; we identified areas for optimization, with the memory allocation being the most obvious one.&lt;/p&gt;
&lt;picture&gt;&lt;source type=&quot;image/avif&quot; srcset=&quot;https://sh4nnongoh.github.io/blog/7-pprof-mem/pS5bweYaPH-3402.avif 3402w&quot;&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://sh4nnongoh.github.io/blog/7-pprof-mem/pS5bweYaPH-3402.webp 3402w&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; src=&quot;https://sh4nnongoh.github.io/blog/7-pprof-mem/pS5bweYaPH-3402.png&quot; alt=&quot;heap-alloc-space&quot; width=&quot;3402&quot; height=&quot;1486&quot;&gt;&lt;/picture&gt;
&lt;p align=&quot;center&quot;&gt;&lt;em&gt;Heap Allocated Space&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;The &lt;em&gt;Magic Link Generation&lt;/em&gt; handler has 2 main areas with high memory allocation: &lt;a href=&quot;https://sh4nnongoh.github.io/blog/7-pprof-mem/#cookie-serialization&quot;&gt;&lt;strong&gt;(1) Cookie Serialization&lt;/strong&gt;&lt;/a&gt;; &lt;a href=&quot;https://sh4nnongoh.github.io/blog/7-pprof-mem/#html-generation&quot;&gt;&lt;strong&gt;(2) HTML Generation&lt;/strong&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;cookie-serialization&quot;&gt;Cookie Serialization&lt;/h2&gt;
&lt;p&gt;The serializer exists to convert client information, in the form of key-value pairs, into an encoded string that represents the cookie. This cookie is attached to the HTTP request.&lt;/p&gt;
&lt;pre class=&quot;language-go&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-go&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// Serialize encodes a value using gob.&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;e GobEncoder&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;Serialize&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;src &lt;span class=&quot;token keyword&quot;&gt;interface&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;byte&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;error&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	buf &lt;span class=&quot;token operator&quot;&gt;:=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;bytes&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Buffer&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
	enc &lt;span class=&quot;token operator&quot;&gt;:=&lt;/span&gt; gob&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;NewEncoder&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;buf&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; err &lt;span class=&quot;token operator&quot;&gt;:=&lt;/span&gt; enc&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Encode&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;src&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; err &lt;span class=&quot;token operator&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;nil&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
		&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;nil&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; cookieError&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;cause&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; err&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; typ&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; usageError&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; buf&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Bytes&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;nil&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Looking at the &lt;a href=&quot;https://github.com/gorilla/securecookie/blob/v1.1.2/securecookie.go#L431&quot;&gt;Serialize&lt;/a&gt; function above, each time it is called a new &lt;em&gt;bytes buffer&lt;/em&gt; is created. This is inefficient as the buffer will be discarded after each request; we need a way to reuse the buffer across requests.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://pkg.go.dev/sync#Pool&quot;&gt;Sync Pool&lt;/a&gt; is a library that aims to solve this, by creating a pool of objects that can be reused without triggering the GC.&lt;/p&gt;
&lt;p&gt;Furthermore, the &lt;em&gt;GobEncoder&lt;/em&gt; uses reflection to infer types during runtime which takes up memory and introduces latency.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/goccy/go-json/&quot;&gt;&lt;em&gt;go-json&lt;/em&gt;&lt;/a&gt; is a library aimed to solve these shortcomings by using &lt;em&gt;Sync Pool&lt;/em&gt; for buffer reuse along with other optimizations mentioned &lt;a href=&quot;https://github.com/goccy/go-json/tree/master?tab=readme-ov-file#basic-technique&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;pre class=&quot;language-go&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-go&quot;&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
   &lt;span class=&quot;token comment&quot;&gt;// ...&lt;/span&gt;
	&lt;span class=&quot;token string&quot;&gt;&quot;bytes&quot;&lt;/span&gt;

	&lt;span class=&quot;token string&quot;&gt;&quot;github.com/goccy/go-json&quot;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; JSONEncoder &lt;span class=&quot;token keyword&quot;&gt;struct&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;e JSONEncoder&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;Serialize&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;src &lt;span class=&quot;token keyword&quot;&gt;interface&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;byte&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;error&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; data &lt;span class=&quot;token keyword&quot;&gt;interface&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;switch&lt;/span&gt; v &lt;span class=&quot;token operator&quot;&gt;:=&lt;/span&gt; src&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;interface&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
		data &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; src
	&lt;span class=&quot;token keyword&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;interface&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;interface&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
		converted &lt;span class=&quot;token operator&quot;&gt;:=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;make&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;interface&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
		&lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; k&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; val &lt;span class=&quot;token operator&quot;&gt;:=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;range&lt;/span&gt; v &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
			converted&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;fmt&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Sprint&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;k&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; val
		&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
		data &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; converted
	&lt;span class=&quot;token keyword&quot;&gt;default&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
		data &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; src
	&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
	buf &lt;span class=&quot;token operator&quot;&gt;:=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;bytes&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Buffer&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
	enc &lt;span class=&quot;token operator&quot;&gt;:=&lt;/span&gt; json&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;NewEncoder&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;buf&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; err &lt;span class=&quot;token operator&quot;&gt;:=&lt;/span&gt; enc&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Encode&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;data&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; err &lt;span class=&quot;token operator&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;nil&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
		&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;nil&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; cookieError&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;cause&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; err&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; typ&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; usageError&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; buf&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Bytes&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;nil&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;e JSONEncoder&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;Deserialize&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;src &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;byte&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; dst &lt;span class=&quot;token keyword&quot;&gt;interface&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;error&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	dec &lt;span class=&quot;token operator&quot;&gt;:=&lt;/span&gt; json&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;NewDecoder&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;bytes&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;NewReader&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;src&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; err &lt;span class=&quot;token operator&quot;&gt;:=&lt;/span&gt; dec&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Decode&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;dst&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; err &lt;span class=&quot;token operator&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;nil&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
		&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; cookieError&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;cause&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; err&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; typ&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; decodeError&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;nil&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;// ...&lt;/span&gt;
  codec &lt;span class=&quot;token operator&quot;&gt;:=&lt;/span&gt; securecookie&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;New&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;authKeyMagic&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; encryptKeyMagic&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  codec&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;SetSerializer&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;JSONEncoder&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;// ...&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Since we are using JSON encoding, we need to cast the &lt;em&gt;interface{}&lt;/em&gt; data type to &lt;em&gt;map[string]interface{}&lt;/em&gt;, in order for the library to serialize successfully.&lt;/p&gt;
&lt;picture&gt;&lt;source type=&quot;image/avif&quot; srcset=&quot;https://sh4nnongoh.github.io/blog/7-pprof-mem/EQNVmX6TC1-3418.avif 3418w&quot;&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://sh4nnongoh.github.io/blog/7-pprof-mem/EQNVmX6TC1-3418.webp 3418w&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; src=&quot;https://sh4nnongoh.github.io/blog/7-pprof-mem/EQNVmX6TC1-3418.png&quot; alt=&quot;heap-alloc-space-serialize-optimize&quot; width=&quot;3418&quot; height=&quot;1478&quot;&gt;&lt;/picture&gt;
&lt;p align=&quot;center&quot;&gt;&lt;em&gt;Heap Allocated Space Serializer Optimized&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;By switching to the new library, we can see the allocated memory drop by &lt;em&gt;~300MB&lt;/em&gt;! That is a significant improvement.&lt;/p&gt;
&lt;h2 id=&quot;html-generation&quot;&gt;HTML Generation&lt;/h2&gt;
&lt;p&gt;The default HTML template parses the the file system for template files and uses reflection at runtime to infer what the HTML should be as seen in the flamegraph. This is done for each request and is extremely slow and memory inefficient.&lt;/p&gt;
&lt;p&gt;Using the &lt;a href=&quot;https://github.com/a-h/templ&quot;&gt;Templ&lt;/a&gt; library, these HTML templates are converted to Go code in the build stage, and compiles down to native binary together with the webserver. As a result, rendering a HTML response is extremely fast with minimal memory allocations.&lt;/p&gt;
&lt;picture&gt;&lt;source type=&quot;image/avif&quot; srcset=&quot;https://sh4nnongoh.github.io/blog/7-pprof-mem/KpTNR-ji-w-3420.avif 3420w&quot;&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://sh4nnongoh.github.io/blog/7-pprof-mem/KpTNR-ji-w-3420.webp 3420w&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; src=&quot;https://sh4nnongoh.github.io/blog/7-pprof-mem/KpTNR-ji-w-3420.png&quot; alt=&quot;heap-alloc-space-html-optimize&quot; width=&quot;3420&quot; height=&quot;1240&quot;&gt;&lt;/picture&gt;
&lt;p align=&quot;center&quot;&gt;&lt;em&gt;Heap Allocated Space HTML Optimized&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;By switching to the new library, we can see the allocated memory further drop by &lt;em&gt;~200MB&lt;/em&gt;! That is another significant improvement.&lt;/p&gt;
&lt;div class=&quot;message-box&quot;&gt;
	&lt;p&gt;
    &lt;em&gt;
      Check out the example project here!
      &lt;br&gt;
      &lt;a href=&quot;https://github.com/sh4nnongoh/go-csrf-magic-links/tree/templ&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;
        https://github.com/sh4nnongoh/go-csrf-magic-links/tree/templ
      &lt;/a&gt;
    &lt;/em&gt;
  &lt;/p&gt;
&lt;/div&gt;

</content>
  </entry>
  <entry>
    <title>pprof Analysis</title>
    <link href="https://sh4nnongoh.github.io/blog/6-pprof-analysis/" />
    <updated>2026-01-31T00:00:00Z</updated>
    <id>https://sh4nnongoh.github.io/blog/6-pprof-analysis/</id>
    <content type="html">&lt;br&gt;
&lt;br&gt;
&lt;div class=&quot;message-box&quot;&gt;
	&lt;p&gt;&lt;em&gt;This is &lt;strong&gt;Part 5&lt;/strong&gt; of the Magic Link System Design Series.&lt;/em&gt;&lt;/p&gt;
  &lt;ol&gt;
    &lt;li&gt;&lt;a href=&quot;https://sh4nnongoh.github.io/blog/2-system-design&quot;&gt;System Design&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&quot;https://sh4nnongoh.github.io/blog/3-magic-links&quot;&gt;Magic Links&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&quot;https://sh4nnongoh.github.io/blog/4-csrf-magic-links&quot;&gt;CSRF with Magic Links&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&quot;https://sh4nnongoh.github.io/blog/5-pprof&quot;&gt;pprof &amp; Load Testing&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;pprof Analysis&lt;/li&gt;
    &lt;li&gt;&lt;a href=&quot;https://sh4nnongoh.github.io/blog/7-pprof-mem&quot;&gt;pprof Memory Optimizations&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&quot;https://sh4nnongoh.github.io/blog/8-pprof-cpu&quot;&gt;pprof CPU&lt;/a&gt;&lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;
&lt;p&gt;Now that we have generated the &lt;a href=&quot;https://sh4nnongoh.github.io/blog/5-pprof&quot;&gt;pprof profiles&lt;/a&gt; for our &lt;em&gt;Magic Link&lt;/em&gt; app, let&#39;s start analyzing them.&lt;/p&gt;
&lt;p&gt;There are a lot of information provided by the profiles, and in order to not get overwhelmed, we need to adopt a strategy to analyze them.&lt;/p&gt;
&lt;h2 id=&quot;strategy&quot;&gt;Strategy&lt;/h2&gt;
&lt;div class=&quot;message-box&quot;&gt;
	&lt;p&gt;&lt;em&gt;
  Flamegraph is a visualization of hierarchical data to visualize stack traces of profiled software so that the most frequent code-paths can be identified quickly and accurately.
  &lt;/em&gt;&lt;br&gt;- brendangregg&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;We will be mostly using &lt;a href=&quot;https://www.brendangregg.com/flamegraphs.html&quot;&gt;flamegraphs&lt;/a&gt; to analyze the profile data. Flamegraphs provide a high level overview of the time or resource spent in certain areas of your app, and because it uses a collection of bar graphs, we can easily identify bottlenecks by looking at the width of a bar relative to the overall app.&lt;/p&gt;
&lt;p&gt;Below are the various sections of profile analysis, and I recommend going through them sequentially in order to not get overwhelmed.&lt;/p&gt;
&lt;h2 id=&quot;table-of-contents&quot;&gt;Table of Contents&lt;/h2&gt;
&lt;hr&gt;
&lt;p&gt;&lt;strong&gt;Resource Utilization&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href=&quot;https://sh4nnongoh.github.io/blog/6-pprof-analysis/#blocking-operation&quot;&gt;Blocking Operation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://sh4nnongoh.github.io/blog/6-pprof-analysis/#mutex&quot;&gt;Mutex&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://sh4nnongoh.github.io/blog/6-pprof-analysis/#goroutine&quot;&gt;Goroutine&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://sh4nnongoh.github.io/blog/6-pprof-analysis/#heap&quot;&gt;Heap&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://sh4nnongoh.github.io/blog/6-pprof-analysis/#cpu&quot;&gt;CPU&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;Latency Reduction&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href=&quot;https://sh4nnongoh.github.io/blog/6-pprof-analysis/#cpu&quot;&gt;CPU&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;hr&gt;
&lt;h2 id=&quot;resource-utilization&quot;&gt;Resource Utilization&lt;/h2&gt;
&lt;h4 id=&quot;blocking-operation&quot;&gt;Blocking Operation&lt;/h4&gt;
&lt;div class=&quot;message-box&quot;&gt;
	&lt;p&gt;&lt;em&gt;
  For I/O-bound latency, blocking profiles reveal goroutines waiting.
  Examples include:
  Network calls (HTTP, database, Redis);
  Channel operations with slow consumers;
  Mutex contention (use mutex profile separately).
  &lt;/em&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;br&gt;
&lt;pre class=&quot;language-bash&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;go tool pprof &lt;span class=&quot;token parameter variable&quot;&gt;-http&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;:8082 ./block.pprof&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Most likely due to the fact that we are running everything on &lt;em&gt;localhost&lt;/em&gt;, hence, there is no information here. Will elaborate more on this in future posts!&lt;/p&gt;
&lt;h4 id=&quot;mutex&quot;&gt;Mutex&lt;/h4&gt;
&lt;div class=&quot;message-box&quot;&gt;
	&lt;p&gt;&lt;em&gt;
  The mutex profile builds on the block profile to focus on mutexes.
  &lt;/em&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;br&gt;
&lt;pre class=&quot;language-bash&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;go tool pprof &lt;span class=&quot;token parameter variable&quot;&gt;-http&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;:8082 ./mutex.pprof&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The &lt;em&gt;Magic Link Generation handler&lt;/em&gt; is currently not dealing with mutexes for resource sharing, hence, there is no information here.&lt;/p&gt;
&lt;h4 id=&quot;goroutine&quot;&gt;Goroutine&lt;/h4&gt;
&lt;div class=&quot;message-box&quot;&gt;
	&lt;p&gt;&lt;em&gt;
  The Goroutine profile shows the goroutines present within the sample period, with each branch representing different types of goroutines triggered within the app. When looking at the flamegraph, identify the total number of goroutines spawned in the top right corner. It should be similar to the number of concurrent requests made during the load test. Also to look out for &quot;waiting on channel that never receives&quot; in your application code to identify leaks.
  &lt;/em&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;br&gt;
&lt;pre class=&quot;language-bash&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;go tool pprof &lt;span class=&quot;token parameter variable&quot;&gt;-http&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;:8082 ./goroutine.pprof&lt;/code&gt;&lt;/pre&gt;
&lt;br&gt;
&lt;picture&gt;&lt;source type=&quot;image/avif&quot; srcset=&quot;https://sh4nnongoh.github.io/blog/6-pprof-analysis/Z3wWVTwucg-3402.avif 3402w&quot;&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://sh4nnongoh.github.io/blog/6-pprof-analysis/Z3wWVTwucg-3402.webp 3402w&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; src=&quot;https://sh4nnongoh.github.io/blog/6-pprof-analysis/Z3wWVTwucg-3402.png&quot; alt=&quot;goroutine&quot; width=&quot;3402&quot; height=&quot;716&quot;&gt;&lt;/picture&gt;
&lt;p align=&quot;center&quot; italic=&quot;&quot;&gt;&lt;em&gt;Number of Goroutines&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;By referencing the flamegraph, it can be seen that the number of goroutines spawned (&lt;em&gt;517&lt;/em&gt;) is approximately equal to the concurrent requests (&lt;em&gt;500&lt;/em&gt;) made during the load test. It can also be seen that there is only one branch of goroutines which is inline with our implementation. In conclusion, there is no issue here.&lt;/p&gt;
&lt;h4 id=&quot;heap&quot;&gt;Heap&lt;/h4&gt;
&lt;div class=&quot;message-box&quot;&gt;
	&lt;p&gt;&lt;em&gt;
  The heap profiles show the amount of memory allocated along with the amount of memory actually in-use during the sample period. The allocated memory is usually large as the Garbage Collector (GC) is constantly reclaiming memory throughout the app lifecycle, whilst the in-use memory details memory that the GC will not work on, and should remain low.
  &lt;/em&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;br&gt;
&lt;pre class=&quot;language-bash&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;go tool pprof &lt;span class=&quot;token parameter variable&quot;&gt;-http&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;:8082 ./heap_rate.pprof&lt;/code&gt;&lt;/pre&gt;
&lt;br&gt;
&lt;picture&gt;&lt;source type=&quot;image/avif&quot; srcset=&quot;https://sh4nnongoh.github.io/blog/6-pprof-analysis/pS5bweYaPH-3402.avif 3402w&quot;&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://sh4nnongoh.github.io/blog/6-pprof-analysis/pS5bweYaPH-3402.webp 3402w&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; src=&quot;https://sh4nnongoh.github.io/blog/6-pprof-analysis/pS5bweYaPH-3402.png&quot; alt=&quot;heap-alloc-space&quot; width=&quot;3402&quot; height=&quot;1486&quot;&gt;&lt;/picture&gt;
&lt;p align=&quot;center&quot;&gt;&lt;em&gt;Heap Allocated Space&lt;/em&gt;&lt;/p&gt;
&lt;br&gt;
&lt;picture&gt;&lt;source type=&quot;image/avif&quot; srcset=&quot;https://sh4nnongoh.github.io/blog/6-pprof-analysis/G5Wt6pgI44-3402.avif 3402w&quot;&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://sh4nnongoh.github.io/blog/6-pprof-analysis/G5Wt6pgI44-3402.webp 3402w&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; src=&quot;https://sh4nnongoh.github.io/blog/6-pprof-analysis/G5Wt6pgI44-3402.png&quot; alt=&quot;heap-in-use-space&quot; width=&quot;3402&quot; height=&quot;918&quot;&gt;&lt;/picture&gt;
&lt;p align=&quot;center&quot;&gt;&lt;em&gt;Heap In-Use Space&lt;/em&gt;&lt;/p&gt;
&lt;details&gt;
  &lt;summary&gt;Click to show/hide  invalid old content&lt;/summary&gt;
&lt;p&gt;I had a wrong understanding on the matter, detailed below.&lt;/p&gt;
&lt;p&gt;&lt;s&gt;Looking at the &lt;em&gt;2&lt;/em&gt; flamegraphs above, it can be seen that the in-use space (&lt;em&gt;10.24MB&lt;/em&gt;) is much smaller than the allocated space (&lt;em&gt;1.33GB&lt;/em&gt;). That means that the current allocated memory utilization is only &lt;strong&gt;~0.7%&lt;/strong&gt;! That is extremely low! The in-use memory utilization is very low as well (&lt;em&gt;10.24MB&lt;/em&gt; / &lt;em&gt;64MB&lt;/em&gt; ~= &lt;strong&gt;16%&lt;/strong&gt;).&lt;/s&gt;&lt;/p&gt;
&lt;p&gt;&lt;s&gt;There are opportunities for improvements here.&lt;/s&gt;&lt;/p&gt;
&lt;p&gt;&lt;s&gt;Remember that our &lt;a href=&quot;https://sh4nnongoh.github.io/blog/5-pprof#docker&quot;&gt;Docker container&lt;/a&gt; is only allocated 64MB of memory? Have you wondered how is it possible for the memory allocation during load test to reach 1.8GB? This is because of the wonderful Garbage Collector present in Go programs. It is so efficient that it can handle our badly written code effectively at scale; i.e. 500 concurrent requests. Memory is constantly allocated per request and discarded at the end. Although the GC is efficient, it still provides an opportunity to make improvements to our app.&lt;/s&gt;&lt;/p&gt;
&lt;p&gt;&lt;s&gt;Basically, we do not want the allocated memory to grow exponentially over time, such that we rely too much on the GC. Each time the GC runs, the app basically pauses and that introduces latency. Once the allocated memory utilization is stable, we mostly likely can increase the number of concurrent requests to increase the in-use memory utilization, making full use of our resources while increasing throughput.&lt;/s&gt;&lt;/p&gt;
&lt;/details&gt;
&lt;p&gt;Looking at the top right corner of each memory profile, we can see the memory allocated or in-use by the app during the load test. I once thought that the high allocated memory was an issue but in fact, that number alone does not mean anything. Instead, we need to take the rate of change of how the allocated memory grows with the increase in concurrent requests. For this app, the allocated memory and in-use memory remains relatively constant as the concurrent requests increases. The in-use memory should also be much lower than the allocated memory to ensure that there are no memory leaks in the app such that the GC is unable to reclaim them; in this case the in-use memory is fine as well.&lt;/p&gt;
&lt;p&gt;Another reason to optimize the allocated memory is when the CPU utilization on GC is high (&amp;gt;10%); more on that in the next section.&lt;/p&gt;
&lt;p&gt;Areas of optimization can be seen in the flamegraph: the &lt;em&gt;Serializer&lt;/em&gt; and the &lt;em&gt;HTML templating engine&lt;/em&gt;.&lt;/p&gt;
&lt;h4 id=&quot;cpu&quot;&gt;CPU&lt;/h4&gt;
&lt;div class=&quot;message-box&quot;&gt;
	&lt;p&gt;&lt;em&gt;
  The CPU profile shows the time spent processing tasks in various sections of the app. The CPU utilization of the app can be calculated by taking the percentage of the CPU time spent (top right corner of the flamegraph) against the sample period. A low CPU utilization means that the app can handle more concurrent requests to make more use of the CPU.
  &lt;/em&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;br&gt;
&lt;pre class=&quot;language-bash&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;go tool pprof &lt;span class=&quot;token parameter variable&quot;&gt;-http&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;:8082 ./cpu.pprof&lt;/code&gt;&lt;/pre&gt;
&lt;br&gt;
&lt;picture&gt;&lt;source type=&quot;image/avif&quot; srcset=&quot;https://sh4nnongoh.github.io/blog/6-pprof-analysis/DXqlG6UlkS-3402.avif 3402w&quot;&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://sh4nnongoh.github.io/blog/6-pprof-analysis/DXqlG6UlkS-3402.webp 3402w&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; src=&quot;https://sh4nnongoh.github.io/blog/6-pprof-analysis/DXqlG6UlkS-3402.png&quot; alt=&quot;cpu&quot; width=&quot;3402&quot; height=&quot;1696&quot;&gt;&lt;/picture&gt;
&lt;p align=&quot;center&quot;&gt;&lt;em&gt;CPU&lt;/em&gt;&lt;/p&gt;
&lt;div class=&quot;message-box&quot;&gt;
	&lt;p&gt;&lt;em&gt;
  Resident Set Size (RSS) is the portion of memory (measured in kilobytes) occupied by a process that is held in main memory (RAM).
  &lt;br&gt;
  - Wikipedia
  &lt;/em&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;br&gt;
&lt;p&gt;The current CPU utilization is (&lt;em&gt;14.83s&lt;/em&gt; / &lt;em&gt;30s&lt;/em&gt; ~= &lt;strong&gt;49%&lt;/strong&gt;). This means that the CPU still has room to process more concurrent requests, but due to the app reaching the RSS limits as seen in the &lt;a href=&quot;https://sh4nnongoh.github.io/blog/5-pprof#docker&quot;&gt;Docker metrics&lt;/a&gt;, the app can&#39;t handle more concurrent requests.&lt;/p&gt;
&lt;picture&gt;&lt;source type=&quot;image/avif&quot; srcset=&quot;https://sh4nnongoh.github.io/blog/6-pprof-analysis/P_sVpYeXVJ-1142.avif 1142w&quot;&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://sh4nnongoh.github.io/blog/6-pprof-analysis/P_sVpYeXVJ-1142.webp 1142w&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; src=&quot;https://sh4nnongoh.github.io/blog/6-pprof-analysis/P_sVpYeXVJ-1142.png&quot; alt=&quot;cpu-gc-top&quot; width=&quot;1142&quot; height=&quot;480&quot;&gt;&lt;/picture&gt;
&lt;p align=&quot;center&quot;&gt;&lt;em&gt;CPU GC (TOP 10)&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;The Top 10 GC related functions utilize only about ~5% of the CPU utilization. Hence, there is no issue with the memory allocation mentioned in the previous section.&lt;/p&gt;
&lt;h2 id=&quot;latency-reduction&quot;&gt;Latency Reduction&lt;/h2&gt;
&lt;h4 id=&quot;cpu-2&quot;&gt;CPU&lt;/h4&gt;
&lt;div class=&quot;message-box&quot;&gt;
	&lt;p&gt;&lt;em&gt;
  When focusing on latency reduction, one needs to dive deep into the sections of the flamegraph to identify optimization areas. Once an area is identified, perform benchmarking to get a baseline of the current metrics, make the necessary improvements, then run the benchmark again to quantify the actual improvements gained.
  &lt;/em&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;br&gt;
&lt;p&gt;Referencing the CPU flamegraph in the previous section, we can see that our &lt;em&gt;Magic Link Generation&lt;/em&gt; handler consumed &lt;em&gt;38.6%&lt;/em&gt; of the overall CPU, and (&lt;em&gt;38.6%&lt;/em&gt; / &lt;em&gt;89.8%&lt;/em&gt; ~= &lt;em&gt;43%&lt;/em&gt;) of the &lt;em&gt;http request &amp;amp; response lifecycle&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Before optimizing the actual application code written by the developer, we should try to remove or reduce other sections of code that consumes the CPU.&lt;/p&gt;
&lt;p&gt;Looking at the &lt;em&gt;fmt.Fprint&lt;/em&gt; under the &lt;em&gt;gin.LoggerWithConfig.func1&lt;/em&gt; section, we can see that it takes up &lt;em&gt;9.2%&lt;/em&gt; of the overall CPU. We can look at optimizing the default &lt;em&gt;logger&lt;/em&gt; for &lt;em&gt;gin&lt;/em&gt;, before optimizing else where.&lt;/p&gt;
&lt;p&gt;When dealing with latency, we will need to do proper benchmarking in-order to quantify the potential gains achieved. &lt;a href=&quot;https://betterstack.com/community/guides/scaling-go/golang-benchmarking/&quot;&gt;Betterstack&lt;/a&gt; has a good article describing this process.&lt;/p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;The app is currently fine and there is no need for optimizations as there will be diminishing returns with respect to the effort needed.&lt;/p&gt;
&lt;p&gt;However for practice, the priority of optimization tasks is as follows:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;To increase the allocated memory utilization of the app.&lt;/li&gt;
&lt;li&gt;To increase the in-use memory utilization of the app.&lt;/li&gt;
&lt;li&gt;To reduce the latency of our app.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;em&gt;Stay tuned to future blog posts where we will dive deep into each area!&lt;/em&gt;&lt;/p&gt;
&lt;div class=&quot;message-box&quot;&gt;
	&lt;p&gt;
    &lt;em&gt;
      Check out the example project here!
      &lt;br&gt;
      &lt;a href=&quot;https://github.com/sh4nnongoh/go-csrf-magic-links&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;
        https://github.com/sh4nnongoh/go-csrf-magic-links
      &lt;/a&gt;
    &lt;/em&gt;
  &lt;/p&gt;
&lt;/div&gt;
</content>
  </entry>
  <entry>
    <title>pprof &amp; Load Testing</title>
    <link href="https://sh4nnongoh.github.io/blog/5-pprof/" />
    <updated>2026-01-26T00:00:00Z</updated>
    <id>https://sh4nnongoh.github.io/blog/5-pprof/</id>
    <content type="html">&lt;br&gt;
&lt;br&gt;
&lt;div class=&quot;message-box&quot;&gt;
	&lt;p&gt;&lt;em&gt;This is &lt;strong&gt;Part 4&lt;/strong&gt; of the Magic Link System Design Series.&lt;/em&gt;&lt;/p&gt;
  &lt;ol&gt;
    &lt;li&gt;&lt;a href=&quot;https://sh4nnongoh.github.io/blog/2-system-design&quot;&gt;System Design&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&quot;https://sh4nnongoh.github.io/blog/3-magic-links&quot;&gt;Magic Links&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&quot;https://sh4nnongoh.github.io/blog/4-csrf-magic-links&quot;&gt;CSRF with Magic Links&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;pprof &amp; Load Testing&lt;/li&gt;
    &lt;li&gt;&lt;a href=&quot;https://sh4nnongoh.github.io/blog/6-pprof-analysis&quot;&gt;pprof Analysis&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&quot;https://sh4nnongoh.github.io/blog/7-pprof-mem&quot;&gt;pprof Memory Optimizations&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&quot;https://sh4nnongoh.github.io/blog/8-pprof-cpu&quot;&gt;pprof CPU&lt;/a&gt;&lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;
&lt;br&gt;
&lt;div class=&quot;message-box&quot;&gt;
  &lt;p&gt;&lt;em&gt;
  pprof is a tool for visualization and analysis of profiling data. It reads a collection of profiling samples in profile.proto format and generates reports to visualize and help analyze the data. It can generate both text and graphical reports (through the use of the dot visualization package).
  &lt;br&gt;
  - Google
  &lt;/em&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;In the &lt;a href=&quot;https://sh4nnongoh.github.io/blog/4-csrf-magic-links&quot;&gt;previous post&lt;/a&gt;, we built a simple &lt;code&gt;Go&lt;/code&gt; webapp using the &lt;code&gt;Gin&lt;/code&gt; webserver for authentication of users using &lt;code&gt;Magic Links&lt;/code&gt;. However, how do we know that it actually works at scale? We need a way to benchmark the app with a proper load and see if it can support the number of users expected to use our app with an appropriate level of resource constraints to match business requirements. This is where &lt;a href=&quot;https://github.com/google/pprof&quot;&gt;pprof&lt;/a&gt; comes in handy, as it is already built into the Go package.&lt;/p&gt;
&lt;pre class=&quot;language-go&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-go&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
	&lt;span class=&quot;token comment&quot;&gt;// ...&lt;/span&gt;

	&lt;span class=&quot;token comment&quot;&gt;//nolint:gosec // G108: pprof is only exposed on internal environments&lt;/span&gt;
	&lt;span class=&quot;token boolean&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;net/http/pprof&quot;&lt;/span&gt;

    &lt;span class=&quot;token comment&quot;&gt;// ...&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;token comment&quot;&gt;// Start pprof HTTP server&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;go&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;func&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
		srv &lt;span class=&quot;token operator&quot;&gt;:=&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;http&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Server&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
			Addr&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;         &lt;span class=&quot;token string&quot;&gt;&quot;:6060&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
			ReadTimeout&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;  &lt;span class=&quot;token number&quot;&gt;5&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; time&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Second&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
			WriteTimeout&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;5&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; time&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Second&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
			IdleTimeout&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;  &lt;span class=&quot;token number&quot;&gt;5&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; time&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Second&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
		&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

		&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; err &lt;span class=&quot;token operator&quot;&gt;:=&lt;/span&gt; srv&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;ListenAndServe&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; err &lt;span class=&quot;token operator&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;nil&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; err &lt;span class=&quot;token operator&quot;&gt;!=&lt;/span&gt; http&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;ErrServerClosed &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
			log&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Fatalf&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;server failed: %v&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; err&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
		&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// ...&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Importing the &lt;code&gt;&amp;quot;net/http/pprof&amp;quot;&lt;/code&gt; package and spinning up a &lt;code&gt;http server&lt;/code&gt;, will enable pprof analysis at the &lt;code&gt;/debug/pprof/&lt;/code&gt; route of your application.&lt;/p&gt;
&lt;p&gt;As a side-note, &lt;code&gt;gosec&lt;/code&gt; linting package will flag this as a security issue as it assumes you are exposing profiling data publicly. Remember that in the larger system architecture, your webserver will not be public facing and is usually hidden behind a proxy. A bastion host is usually setup for system administrators or engineers to interact with the pprof endpoints. Therefore, we can ignore this specific linting rule.&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token assign-left variable&quot;&gt;BASE_URL&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;http://localhost:6060
&lt;span class=&quot;token assign-left variable&quot;&gt;SAMPLING_PERIOD&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;30&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;# CPU Profile&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;curl&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-s&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token variable&quot;&gt;${BASE_URL}&lt;/span&gt;/debug/pprof/profile?seconds=&lt;span class=&quot;token variable&quot;&gt;${SAMPLING_PERIOD}&lt;/span&gt;&quot;&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;# I/O Profile&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;curl&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-s&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token variable&quot;&gt;${BASE_URL}&lt;/span&gt;/debug/pprof/block?seconds=&lt;span class=&quot;token variable&quot;&gt;${SAMPLING_PERIOD}&lt;/span&gt;&quot;&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;# Lock Contention Profile&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;curl&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-s&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token variable&quot;&gt;${BASE_URL}&lt;/span&gt;/debug/pprof/mutex?seconds=&lt;span class=&quot;token variable&quot;&gt;${SAMPLING_PERIOD}&lt;/span&gt;&quot;&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;# # To answer: &quot;How many objects are we creating per request?&quot;&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;curl&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-s&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token variable&quot;&gt;${BASE_URL}&lt;/span&gt;/debug/pprof/heap?seconds=&lt;span class=&quot;token variable&quot;&gt;${SAMPLING_PERIOD}&lt;/span&gt;&quot;&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;# Goroutine Profile&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;curl&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-s&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token variable&quot;&gt;${BASE_URL}&lt;/span&gt;/debug/pprof/goroutine?debug=2&quot;&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;# Save inuse_objects (currently live objects)&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;curl&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-s&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token variable&quot;&gt;${BASE_URL}&lt;/span&gt;/debug/pprof/heap&quot;&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;# Save inuse_space (bytes currently in use)&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;curl&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-s&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token variable&quot;&gt;${BASE_URL}&lt;/span&gt;/debug/pprof/heap&quot;&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;# The ?gc=1 parameter triggers garbage collection before sampling&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;# Save alloc_objects (total allocations during profile)&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;curl&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-s&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token variable&quot;&gt;${BASE_URL}&lt;/span&gt;/debug/pprof/heap?gc=1&quot;&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;# Save alloc_space (bytes allocated)&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;curl&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-s&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token variable&quot;&gt;${BASE_URL}&lt;/span&gt;/debug/pprof/heap?gc=1&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Once the server is up, we can gather metrics of our system by perform a &lt;code&gt;GET&lt;/code&gt; request on the respective endpoints shown above.&lt;/p&gt;
&lt;p&gt;We can then use the command line &lt;code&gt;go tool&lt;/code&gt; to evaluate each profile accordingly; i.e. &lt;code&gt;go tool pprof -http=:8081 ./cpu.pprof&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;The &lt;a href=&quot;https://github.com/sh4nnongoh/go-csrf-magic-links/blob/main/cmd/benchmark/start.sh&quot;&gt;benchmarking script&lt;/a&gt; is defined in the repository as well.&lt;/p&gt;
&lt;h2 id=&quot;load-testing&quot;&gt;Load Testing&lt;/h2&gt;
&lt;p&gt;Now that our server is ready to gather profiling metrics. We need to write a script to perform actual load testing on our server.&lt;/p&gt;
&lt;pre class=&quot;language-go&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-go&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// ...&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
	ConcurrentRequestsCount   &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;500&lt;/span&gt;
	BenchmarkDurationSeconds  &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;60&lt;/span&gt;
	Host                      &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;http://127.0.0.1:8080&quot;&lt;/span&gt;
	GenerateMagicRoute        &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;/magic/generate&quot;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;

    &lt;span class=&quot;token comment&quot;&gt;// ...&lt;/span&gt;

	client &lt;span class=&quot;token operator&quot;&gt;:=&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;http&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Client&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
		Timeout&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;5&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; time&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Second&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token comment&quot;&gt;// (1) Defining Context and Resource Management Constructs&lt;/span&gt;
	ctx&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; cancel &lt;span class=&quot;token operator&quot;&gt;:=&lt;/span&gt; context&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;WithTimeout&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;context&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Background&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; BenchmarkDurationSeconds&lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;time&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Second&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;defer&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;cancel&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
	group&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; ctx &lt;span class=&quot;token operator&quot;&gt;:=&lt;/span&gt; errgroup&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;WithContext&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;ctx&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
	semaphore &lt;span class=&quot;token operator&quot;&gt;:=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;make&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;chan&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;struct&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; ConcurrentRequestsCount&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

loop&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
		&lt;span class=&quot;token keyword&quot;&gt;select&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
		&lt;span class=&quot;token keyword&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;-&lt;/span&gt;ctx&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Done&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
			&lt;span class=&quot;token keyword&quot;&gt;break&lt;/span&gt; loop
		&lt;span class=&quot;token keyword&quot;&gt;default&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;token comment&quot;&gt;// (2) Trigger Requests in Goroutines&lt;/span&gt;
			semaphore &lt;span class=&quot;token operator&quot;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;struct&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
			group&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Go&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;func&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;error&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
				&lt;span class=&quot;token keyword&quot;&gt;defer&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;func&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
					&lt;span class=&quot;token operator&quot;&gt;&amp;lt;-&lt;/span&gt;semaphore
				&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
				req&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; err &lt;span class=&quot;token operator&quot;&gt;:=&lt;/span&gt; http&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;NewRequestWithContext&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;ctx&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; http&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;MethodPost&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; Host&lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt;GenerateMagicRoute&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;nil&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
				&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; err &lt;span class=&quot;token operator&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;nil&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
					&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; err
				&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
				req&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Header&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Set&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;X-CSRF-Token&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;generateCsrf&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
				res&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; err &lt;span class=&quot;token operator&quot;&gt;:=&lt;/span&gt; client&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Do&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;req&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
				&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; err &lt;span class=&quot;token operator&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;nil&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
					&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; err
				&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
                &lt;span class=&quot;token comment&quot;&gt;// Important! Need to read the body to release the http connection back to the pool.&lt;/span&gt;
				io&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;ReadAll&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;res&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Body&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
				&lt;span class=&quot;token keyword&quot;&gt;defer&lt;/span&gt; res&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Body&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Close&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
				&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;nil&lt;/span&gt;
			&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
		&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; err &lt;span class=&quot;token operator&quot;&gt;:=&lt;/span&gt; group&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Wait&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; err &lt;span class=&quot;token operator&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;nil&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
		log&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Println&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;request failed:&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; err&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token comment&quot;&gt;// ...&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In the &lt;a href=&quot;https://github.com/sh4nnongoh/go-csrf-magic-links/blob/main/cmd/benchmark/main.go&quot;&gt;&lt;code&gt;/cmd/benchmark/main.go&lt;/code&gt;&lt;/a&gt; directory, a &lt;code&gt;Go&lt;/code&gt; program is written to perform concurrent requests to the server&#39;s endpoints.&lt;/p&gt;
&lt;h4 id=&quot;1-defining-context-and-resource-management-constructs&quot;&gt;(1) Defining Context &amp;amp; Resource Management Constructs&lt;/h4&gt;
&lt;p&gt;A &lt;code&gt;context&lt;/code&gt; is defined with a timeout parameter, to tell our program to exit once it reaches the time limit. This context is attached to an &lt;code&gt;errgroup&lt;/code&gt; which is the construct that performs the actual concurrent requests. &lt;em&gt;(For those familiar with &lt;code&gt;Javascript&lt;/code&gt;, an &lt;code&gt;errgroup&lt;/code&gt; is similar to &lt;code&gt;Promise.All()&lt;/code&gt;).&lt;/em&gt; A semaphore is also defined which represents the maximum number of concurrent requests that can be made to our server.&lt;/p&gt;
&lt;h4 id=&quot;2-trigger-requests-in-goroutines&quot;&gt;(2) Trigger Requests in Goroutines&lt;/h4&gt;
&lt;p&gt;The whole request lifecycle is encapsulated within a &lt;code&gt;Goroutine&lt;/code&gt;, and this &lt;code&gt;Goroutine&lt;/code&gt; is only triggered once a &lt;em&gt;lock&lt;/em&gt; can be claimed from the &lt;em&gt;semaphore&lt;/em&gt;. For this load testing, the endpoint for &lt;code&gt;Magic Link&lt;/code&gt; generation will be used.&lt;/p&gt;
&lt;p&gt;An important note when performing a high number of HTTP requests is that most libraries will pool the HTTP connections, such that the program does not overload the number of network sockets on the system. In order for a HTTP connection to be considered &lt;code&gt;&amp;quot;completed&amp;quot;&lt;/code&gt;, the &lt;code&gt;body&lt;/code&gt; of the response received after performing a request needs to be read fully. Otherwise, the HTTP connection will not be returned to the connection pool, and as a result, the client will experience a socket exhaustion error while performing the load test.&lt;/p&gt;
&lt;h3 id=&quot;docker&quot;&gt;Docker&lt;/h3&gt;
&lt;div class=&quot;message-box&quot;&gt;
  &lt;p&gt;&lt;em&gt;
  &quot;What do you mean there is an issue? IT WORKS ON MY MACHINE!&quot;
  &lt;br&gt;
  - I am always right engineer
  &lt;/em&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;In order for our experiment to produce consistent results, we leverage on &lt;code&gt;Containers&lt;/code&gt; to encapsulate our program.&lt;/p&gt;
&lt;pre class=&quot;language-docker&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-docker&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;# Stage 1: Build the Go application&lt;/span&gt;
&lt;span class=&quot;token instruction&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;FROM&lt;/span&gt; golang:1.25-alpine &lt;span class=&quot;token keyword&quot;&gt;AS&lt;/span&gt; builder&lt;/span&gt;

&lt;span class=&quot;token instruction&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;WORKDIR&lt;/span&gt; /app&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;# Copy go mod files&lt;/span&gt;
&lt;span class=&quot;token instruction&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;COPY&lt;/span&gt; go.mod go.sum ./&lt;/span&gt;
&lt;span class=&quot;token instruction&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;RUN&lt;/span&gt; go mod download&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;# Copy source code&lt;/span&gt;
&lt;span class=&quot;token instruction&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;COPY&lt;/span&gt; . .&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;# Build the application with optimizations&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;# -ldflags=&quot;-s -w&quot; strips debug symbols, reducing binary size&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;# CGO_ENABLED=0 creates static binary, no C dependencies&lt;/span&gt;
&lt;span class=&quot;token instruction&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;RUN&lt;/span&gt; CGO_ENABLED=0 GOOS=linux go build -ldflags=&lt;span class=&quot;token string&quot;&gt;&quot;-s -w&quot;&lt;/span&gt; -a -o main .&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;# Stage 2: Create minimal runtime image&lt;/span&gt;
&lt;span class=&quot;token instruction&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;FROM&lt;/span&gt; scratch&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;# Copy only the built binary, and public assets from the builder stage&lt;/span&gt;
&lt;span class=&quot;token instruction&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;COPY&lt;/span&gt; &lt;span class=&quot;token options&quot;&gt;&lt;span class=&quot;token property&quot;&gt;--from&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;builder&lt;/span&gt;&lt;/span&gt; /app/main /main&lt;/span&gt;
&lt;span class=&quot;token instruction&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;COPY&lt;/span&gt; &lt;span class=&quot;token options&quot;&gt;&lt;span class=&quot;token property&quot;&gt;--from&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;builder&lt;/span&gt;&lt;/span&gt; /app/static /static&lt;/span&gt;
&lt;span class=&quot;token instruction&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;COPY&lt;/span&gt; &lt;span class=&quot;token options&quot;&gt;&lt;span class=&quot;token property&quot;&gt;--from&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;builder&lt;/span&gt;&lt;/span&gt; /app/templates /templates&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;# Copy CA certificates for HTTPS if needed&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;# COPY --from=builder /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;# Expose ports&lt;/span&gt;
&lt;span class=&quot;token instruction&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;EXPOSE&lt;/span&gt; 8080 6060&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;# Run as non-root user for security&lt;/span&gt;
&lt;span class=&quot;token instruction&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;USER&lt;/span&gt; 1000:1000&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;# Set minimal environment&lt;/span&gt;
&lt;span class=&quot;token instruction&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;ENV&lt;/span&gt; GOMAXPROCS=1&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;# Health check&lt;/span&gt;
&lt;span class=&quot;token instruction&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;HEALTHCHECK&lt;/span&gt; &lt;span class=&quot;token options&quot;&gt;&lt;span class=&quot;token property&quot;&gt;--interval&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;30s&lt;/span&gt; &lt;span class=&quot;token property&quot;&gt;--timeout&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;3s&lt;/span&gt; &lt;span class=&quot;token property&quot;&gt;--start-period&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;5s&lt;/span&gt; &lt;span class=&quot;token property&quot;&gt;--retries&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;3&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&#92;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;CMD&lt;/span&gt; [&lt;span class=&quot;token string&quot;&gt;&quot;/main&quot;&lt;/span&gt;, &lt;span class=&quot;token string&quot;&gt;&quot;health&quot;&lt;/span&gt;] || exit 1&lt;/span&gt;

&lt;span class=&quot;token instruction&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;ENTRYPOINT&lt;/span&gt; [&lt;span class=&quot;token string&quot;&gt;&quot;/main&quot;&lt;/span&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The above script shows a &lt;code&gt;Dockerfile&lt;/code&gt;, for packaging our application into a production ready container.&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;docker&lt;/span&gt; run &lt;span class=&quot;token parameter variable&quot;&gt;-d&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;&#92;&lt;/span&gt;  &lt;span class=&quot;token parameter variable&quot;&gt;--name&lt;/span&gt; myapp &lt;span class=&quot;token punctuation&quot;&gt;&#92;&lt;/span&gt;
  &lt;span class=&quot;token parameter variable&quot;&gt;--memory&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;64m &lt;span class=&quot;token punctuation&quot;&gt;&#92;&lt;/span&gt;     
  --memory-swap&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;64m &lt;span class=&quot;token punctuation&quot;&gt;&#92;&lt;/span&gt;
  --memory-swappiness&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;&#92;&lt;/span&gt;
  &lt;span class=&quot;token parameter variable&quot;&gt;--cpus&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;0.5&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;&#92;&lt;/span&gt;
  &lt;span class=&quot;token parameter variable&quot;&gt;-p&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;8080&lt;/span&gt;:8080 &lt;span class=&quot;token punctuation&quot;&gt;&#92;&lt;/span&gt;
  &lt;span class=&quot;token parameter variable&quot;&gt;-p&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;6060&lt;/span&gt;:6060 &lt;span class=&quot;token punctuation&quot;&gt;&#92;&lt;/span&gt;
  &lt;span class=&quot;token parameter variable&quot;&gt;-e&lt;/span&gt; &lt;span class=&quot;token assign-left variable&quot;&gt;GIN_MODE&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;release &lt;span class=&quot;token punctuation&quot;&gt;&#92;&lt;/span&gt;
  myapp:latest&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;When invoking the container, a strict constrained environment can be defined to test specific areas of our application. An example is shown above.&lt;/p&gt;
&lt;picture&gt;&lt;source type=&quot;image/avif&quot; srcset=&quot;https://sh4nnongoh.github.io/blog/5-pprof/5OQn4HWpsr-2916.avif 2916w&quot;&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://sh4nnongoh.github.io/blog/5-pprof/5OQn4HWpsr-2916.webp 2916w&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; src=&quot;https://sh4nnongoh.github.io/blog/5-pprof/5OQn4HWpsr-2916.png&quot; alt=&quot;Docker Desktop Metrics&quot; width=&quot;2916&quot; height=&quot;1816&quot;&gt;&lt;/picture&gt;
&lt;p&gt;The parameters of our &lt;a href=&quot;https://sh4nnongoh.github.io/blog/5-pprof/#load-testing&quot;&gt;Load Testing script&lt;/a&gt; can be defined by experimenting with the values, and observing the stability of the container metrics in the Docker Desktop UI. In our scenario, &lt;code&gt;500&lt;/code&gt; concurrent requests is a good number to start with for a &lt;code&gt;64MB&lt;/code&gt; container.&lt;/p&gt;
&lt;div class=&quot;message-box&quot;&gt;
	&lt;p&gt;
    &lt;em&gt;
      Check out the example project here!
      &lt;br&gt;
      &lt;a href=&quot;https://github.com/sh4nnongoh/go-csrf-magic-links&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;
        https://github.com/sh4nnongoh/go-csrf-magic-links
      &lt;/a&gt;
    &lt;/em&gt;
  &lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;More details into &lt;code&gt;pprof&lt;/code&gt; analysis will be in the next post. Stay tuned!&lt;/p&gt;

</content>
  </entry>
  <entry>
    <title>CSRF with Magic Links</title>
    <link href="https://sh4nnongoh.github.io/blog/4-csrf-magic-links/" />
    <updated>2026-01-22T00:00:00Z</updated>
    <id>https://sh4nnongoh.github.io/blog/4-csrf-magic-links/</id>
    <content type="html">&lt;br&gt;
&lt;br&gt;
&lt;div class=&quot;message-box&quot;&gt;
	&lt;p&gt;&lt;em&gt;This is &lt;strong&gt;Part 3&lt;/strong&gt; of the Magic Link System Design Series.&lt;/em&gt;&lt;/p&gt;
  &lt;ol&gt;
    &lt;li&gt;&lt;a href=&quot;https://sh4nnongoh.github.io/blog/2-system-design&quot;&gt;System Design&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&quot;https://sh4nnongoh.github.io/blog/3-magic-links&quot;&gt;Magic Links&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;CSRF with Magic Links&lt;/li&gt;
    &lt;li&gt;&lt;a href=&quot;https://sh4nnongoh.github.io/blog/5-pprof&quot;&gt;pprof &amp; Load Testing&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&quot;https://sh4nnongoh.github.io/blog/6-pprof-analysis&quot;&gt;pprof Analysis&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&quot;https://sh4nnongoh.github.io/blog/7-pprof-mem&quot;&gt;pprof Memory Optimizations&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&quot;https://sh4nnongoh.github.io/blog/8-pprof-cpu&quot;&gt;pprof CPU&lt;/a&gt;&lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;
&lt;p&gt;As a recap, a Magic Link contains an encrypted token containing the identity of a particular user. By that definition, anyone clicking that link can impersonate the identify encoded in the link. Doesn&#39;t that sound familiar? (&lt;em&gt;Cough, Cough&lt;/em&gt; - &lt;strong&gt;Netflix&lt;/strong&gt;)&lt;/p&gt;
&lt;p&gt;In order to prevent that we need a way for the link to only work for the original requester, and that is where &lt;em&gt;CSRF tokens&lt;/em&gt; come in handy.&lt;/p&gt;
&lt;div class=&quot;message-box&quot;&gt;
  &lt;p&gt;&lt;em&gt;
  Cross-Site Request Forgery (CSRF) is an attack that forces an end user to execute unwanted actions on a web application in which they’re currently authenticated. With a little help of social engineering (such as sending a link via email or chat), an attacker may trick the users of a web application into executing actions of the attacker’s choosing. If the victim is a normal user, a successful CSRF attack can force the user to perform state changing requests like transferring funds, changing their email address, and so forth. If the victim is an administrative account, CSRF can compromise the entire web application.
  &lt;br&gt;
  - OWASP
  &lt;/em&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;h3 id=&quot;csrf-cookies&quot;&gt;CSRF + Cookies&lt;/h3&gt;
&lt;p&gt;Before discussing &lt;em&gt;CSRF tokens&lt;/em&gt; with &lt;em&gt;Magic Links&lt;/em&gt;, let&#39;s take a look at how &lt;em&gt;CSRF tokens&lt;/em&gt; work with cookies. After a user gets authenticated, a cookie is usually created by the server and assigned to the user. This cookie would contain data identifying the user, and will be attached to every request made by the user to the server. Knowing this, an adversary could trick users into submitting authenticated transactions without their knowledge. A common example would be the user visiting the adversary site which triggers requests to a known webapp used by the user.&lt;/p&gt;
&lt;pre class=&quot;language-html&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;&amp;lt;!-- Adversary site has the following elements --&gt;&lt;/span&gt;

 &lt;span class=&quot;token comment&quot;&gt;&amp;lt;!-- A form that secretly performs a POST 
  to a known site used by the User --&gt;&lt;/span&gt;
&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;form&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;action&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;https://bank.example.com/transfer&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;method&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;POST&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;input&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;hidden&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;to_account&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;attacker123&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;input&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;hidden&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;amount&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;1000&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;form&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;&amp;lt;!-- OR --&gt;&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;&amp;lt;!-- Loading an img element which basically 
 performs a hidden GET request --&gt;&lt;/span&gt;
&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;img&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;src&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;https://bank.example.com/transfer?to=attacker123&amp;amp;amount=1000&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;div class=&quot;message-box&quot;&gt;
  &lt;p&gt;&lt;em&gt;
  A CSRF token is a nounce of a certain size that is random across sessions and users.
  &lt;/em&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;In order to prevent such attacks, the &lt;em&gt;CSRF token&lt;/em&gt; needs to be sent with the requests alongside the authentication cookies. The server will compare the request&#39;s &lt;em&gt;CSRF token&lt;/em&gt; with the session&#39;s state, which could either be stored server-side like in Redis, or &lt;a href=&quot;https://sh4nnongoh.github.io/blog/3-magic-links/#sequence-diagrams&quot;&gt;in our scenario&lt;/a&gt;, in the encrypted cookie.&lt;/p&gt;
&lt;picture&gt;&lt;source type=&quot;image/avif&quot; srcset=&quot;https://sh4nnongoh.github.io/blog/4-csrf-magic-links/lZd_YgLNA4-439.avif 439w&quot;&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://sh4nnongoh.github.io/blog/4-csrf-magic-links/lZd_YgLNA4-439.webp 439w&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; src=&quot;https://sh4nnongoh.github.io/blog/4-csrf-magic-links/lZd_YgLNA4-439.png&quot; alt=&quot;Sequence Diagram&quot; width=&quot;439&quot; height=&quot;478&quot;&gt;&lt;/picture&gt;
&lt;p&gt;The above &lt;a href=&quot;https://www.websequencediagrams.com/?lz=dGl0bGUgTG9naW4gd2l0aCBDb29raWVzCgphY3RvciBVc2VyCgovbAAcBS0-AAsFIDoAAQZ2aXNpdHMgcGFnZQA2BlxuQ1NSRiB0b2tlbiBlbWJlZGRlZAoKAC8FLT4gAEAGADYHc3VibWl0cyBjcmVkZW50aWFscyBcbgB9BgA7CmluIGhlYWRlcgB6CQB6ClJldHVybnMgZW5jcnlwdGVkIGMAgTcFIFxuY29udGFpbmluZwBCCwB-C3NlY3VyZQCBQAh0cmFuc2FjdHMAgXwGABYHcGFnZXMgXG51c2luZwBTEmFuZACBEhcAVgcAgSAKCg&amp;amp;s=default&quot;&gt;sequence diagram&lt;/a&gt; shows the following:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;When the user navigates to the &lt;em&gt;/login&lt;/em&gt; page, a &lt;em&gt;CSRF token&lt;/em&gt; generated by the server is present in the &lt;em&gt;meta&lt;/em&gt; tag of the page.&lt;/li&gt;
&lt;li&gt;Upon logging in, the &lt;em&gt;CSRF token&lt;/em&gt; is attached in the &lt;em&gt;header&lt;/em&gt; of the &lt;em&gt;POST&lt;/em&gt; request along with the login credentials.&lt;/li&gt;
&lt;li&gt;The server verifies the credentials and, if successful, creates an encrypted cookie containing the user&#39;s identity along with the &lt;em&gt;CSRF token&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;Any future authenticated requests made to the server will have the attached &lt;em&gt;CSRF token&lt;/em&gt; in the header compared with the &lt;em&gt;CSRF token&lt;/em&gt; stored in the encrypted cookie. Even if the cookie is valid, an invalid &lt;em&gt;CSRF token&lt;/em&gt; check will render the request invalid.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;There is no way for an adversary site to capture this &lt;em&gt;CSRF token&lt;/em&gt; embedded in our site.&lt;/p&gt;
&lt;h3 id=&quot;csrf-magic-links&quot;&gt;CSRF + Magic Links&lt;/h3&gt;
&lt;p&gt;A &lt;em&gt;Magic Link&lt;/em&gt; basically has the encrypted cookie as part of the URL. The question now is how does the user send the &lt;em&gt;CSRF token&lt;/em&gt; in the header by just clicking a link? You might have noticed when using certain secure sites like banking, there is some sort of &lt;em&gt;&amp;quot;/verification&amp;quot;&lt;/em&gt; intemediary page before the site shows you your dashboard. This intermediary page actually captures the encrypted cookie in the &lt;em&gt;Magic Link&lt;/em&gt; along with the &lt;em&gt;CSRF token&lt;/em&gt; in the browser and performs the actual POST request of logging into the secure site.&lt;/p&gt;
&lt;picture&gt;&lt;source type=&quot;image/avif&quot; srcset=&quot;https://sh4nnongoh.github.io/blog/4-csrf-magic-links/cMXV3k-0Je-515.avif 515w&quot;&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://sh4nnongoh.github.io/blog/4-csrf-magic-links/cMXV3k-0Je-515.webp 515w&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; src=&quot;https://sh4nnongoh.github.io/blog/4-csrf-magic-links/cMXV3k-0Je-515.png&quot; alt=&quot;Sequence Diagram&quot; width=&quot;515&quot; height=&quot;510&quot;&gt;&lt;/picture&gt;
&lt;p&gt;The above &lt;a href=&quot;https://www.websequencediagrams.com/cgi-bin/cdraw?lz=dGl0bGUgTG9naW4gd2l0aCBNYWdpYyBMaW5rCgphY3RvciBVc2VyCgovdmVyaWZpY2F0aW9uIC0-ABIFIDoAAQZjbGlja3Mgb24ANAsgJiBcbm5hdmlnYXRlcyB0byAANQ1wYWdlCgA_BS0-IABPDjogQW4gYXV0b21hdGVkIFBPU1QgcmVxdWVzdCBpcyBkb25lIFxuY29udGFpbmluZyB0aGUgZW5jcnlwdGVkIHRva2VuIFxuYW5kIENTUkYACgdpbgAjBWhlYWRlcgCBPxAAgUYKU2V2ZXIgZ2VuZXIAgTMFYSBuZXcAUwtjb29raWUgXG5mb3IAdAVzZXNzaW9uICYgcmVkaXJlY3RzAIEMBXVzZXIgXG50bwAfB2N1cmUgcmVzb3VyY2UKAIFxCgATBwCCQwd0cmFuc2FjdHMAgwgGADAHcGFnZXMgXG51c2luZwB7EgCBWBIAgV4IAHAHAIFWCgo&amp;amp;s=default&quot;&gt;sequence diagram&lt;/a&gt; shows the following:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;The &lt;em&gt;Magic Link&lt;/em&gt; navigates the user to the &lt;em&gt;&amp;quot;/verification&amp;quot;&lt;/em&gt; page.&lt;/li&gt;
&lt;li&gt;The &lt;em&gt;&amp;quot;/verification&amp;quot;&lt;/em&gt; page performs a POST request with the encrypted cookie and &lt;em&gt;CSRF token&lt;/em&gt; to login the user.&lt;/li&gt;
&lt;li&gt;The server decrypts the cookie and compare the embedded &lt;em&gt;CSRF token&lt;/em&gt;, with the token in the &lt;em&gt;header&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;If valid, a new session is created for the user with a new encrypted cookie returned to the user.&lt;/li&gt;
&lt;li&gt;Future requests to the secure site, will have the encrypted cookie in the request. The client will have to send the &lt;em&gt;CSRF token&lt;/em&gt; in the header for the requests to be successful.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;When navigating the secure site through the UI, the &lt;em&gt;CSRF token&lt;/em&gt; can be easily accessed to be attached to the request. However, if the user were to click on a link to access the site, a &lt;em&gt;&amp;quot;/verification&amp;quot;&lt;/em&gt; page willstill be needed to properly authenticate the user by capturing the &lt;em&gt;CSRF token&lt;/em&gt; in the browser.&lt;/p&gt;
&lt;p&gt;So back to the issue at hand, the &lt;em&gt;Magic Link&lt;/em&gt; needs to only work in the same browser that triggers the &lt;em&gt;Magic Link&lt;/em&gt; generation. Similar to the &lt;em&gt;/login&lt;/em&gt; page example in the previous section, the &lt;em&gt;CSRF token&lt;/em&gt; is embedded in the browser when the users generate a &lt;em&gt;Magic Link&lt;/em&gt; with their email. Therefore, the Magic Link sent to their emails will only work if the users open the links with the same browser session that triggered the generation; as that is where the &lt;em&gt;CSRF token&lt;/em&gt; is embedded.&lt;/p&gt;
&lt;h2 id=&quot;implemention&quot;&gt;Implemention&lt;/h2&gt;
&lt;p&gt;In this section we will cover the implementation details for a minimal CSRF Magic Link example with &lt;em&gt;Go&lt;/em&gt;, &lt;em&gt;Gin&lt;/em&gt;, &lt;em&gt;HTML templating&lt;/em&gt;, and &lt;em&gt;HTMX&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;HTMX&lt;/em&gt; is amazing but we will not be covering that in this post.&lt;/p&gt;
&lt;p&gt;The web server is setup as follow:&lt;/p&gt;
&lt;pre class=&quot;language-go&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-go&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;package&lt;/span&gt; main

&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
	&lt;span class=&quot;token string&quot;&gt;&quot;crypto/rand&quot;&lt;/span&gt;
	&lt;span class=&quot;token string&quot;&gt;&quot;net/http&quot;&lt;/span&gt;

	&lt;span class=&quot;token string&quot;&gt;&quot;github.com/gin-contrib/sessions&quot;&lt;/span&gt;
	&lt;span class=&quot;token string&quot;&gt;&quot;github.com/gin-contrib/sessions/cookie&quot;&lt;/span&gt;
	&lt;span class=&quot;token string&quot;&gt;&quot;github.com/gin-gonic/gin&quot;&lt;/span&gt;
	&lt;span class=&quot;token string&quot;&gt;&quot;github.com/gorilla/securecookie&quot;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// (1) Defining keys &amp;amp; store&lt;/span&gt;
	authKeyMagic &lt;span class=&quot;token operator&quot;&gt;:=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;make&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;byte&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;32&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
	encryptKeyMagic &lt;span class=&quot;token operator&quot;&gt;:=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;make&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;byte&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;32&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
	rand&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Read&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;authKeyMagic&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
	rand&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Read&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;encryptKeyMagic&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
	codec &lt;span class=&quot;token operator&quot;&gt;:=&lt;/span&gt; securecookie&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;New&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;authKeyMagic&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; encryptKeyMagic&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
	codec&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;MaxAge&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;60&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;60&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;15&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
	codecs &lt;span class=&quot;token operator&quot;&gt;:=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;securecookie&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Codec&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;codec&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

	authKeyCookie &lt;span class=&quot;token operator&quot;&gt;:=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;make&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;byte&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;32&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
	encryptKeyCookie &lt;span class=&quot;token operator&quot;&gt;:=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;make&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;byte&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;32&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
	rand&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Read&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;authKeyCookie&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
	rand&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Read&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;encryptKeyCookie&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
	storeCookies &lt;span class=&quot;token operator&quot;&gt;:=&lt;/span&gt; cookie&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;NewStore&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;authKeyCookie&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; encryptKeyCookie&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
	storeCookies&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Options&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;sessions&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Options&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
		Path&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;     &lt;span class=&quot;token string&quot;&gt;&quot;/&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
		MaxAge&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;   &lt;span class=&quot;token number&quot;&gt;60&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;60&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;60&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
		HttpOnly&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
		Secure&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;   &lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;token comment&quot;&gt;// (2) Routes&lt;/span&gt;
	router &lt;span class=&quot;token operator&quot;&gt;:=&lt;/span&gt; gin&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Default&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
	err &lt;span class=&quot;token operator&quot;&gt;:=&lt;/span&gt; router&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;SetTrustedProxies&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;127.0.0.1&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; err &lt;span class=&quot;token operator&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;nil&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
		&lt;span class=&quot;token function&quot;&gt;panic&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;err&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
	router&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;LoadHTMLGlob&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;templates/*.go.tmpl&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
	router&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Static&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;/static&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;./static&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
	router&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Use&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;sessions&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Sessions&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;COOKIE_STORE_NAME&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; storeCookies&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
	router&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;POST&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;/magic/generate&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;handleMagicLinkGeneration&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;codecs&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
	router&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;POST&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;/magic/verify/:magic&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;handleMagicLinkVerification&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;codecs&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
	router&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;GET&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;/magic/verify/:magic&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;func&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;c &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;gin&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Context&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
		c&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;HTML&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;http&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;StatusOK&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;check-auth.go.tmpl&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; gin&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;H&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
			&lt;span class=&quot;token string&quot;&gt;&quot;route&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
		&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
	router&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;GET&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;/secure/:id&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;func&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;c &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;gin&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Context&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
		c&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;HTML&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;http&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;StatusOK&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;check-auth.go.tmpl&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; gin&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;H&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
			&lt;span class=&quot;token string&quot;&gt;&quot;route&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; c&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Request&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;URL&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Path&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
		&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
	router&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;POST&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;/secure/:id&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; handleSecure&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
	router&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;GET&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;/login&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;MiddlewareNoCache&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;func&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;c &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;gin&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Context&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
		c&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;HTML&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;http&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;StatusOK&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;login.go.tmpl&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; gin&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;H&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
			&lt;span class=&quot;token string&quot;&gt;&quot;csrfToken&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;generateCsrf&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
		&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
	router&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Run&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h4 id=&quot;1-defining-keys-and-store&quot;&gt;(1) Defining keys &amp;amp; store&lt;/h4&gt;
&lt;div class=&quot;message-box&quot;&gt;
  &lt;p&gt;&lt;em&gt;
  Hash-based Message Authentication Code (HAMC), is a cryptographic technique that combines a hash function with a secret key to verify the integrity and authenticity of a message. It ensures that the message has not been altered during transmission and confirms that it comes from a legitimate source.
  &lt;/em&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;br&gt;
&lt;p&gt;The reason why we have 2 keys, is that one is used for &lt;em&gt;HMAC&lt;/em&gt; while the other is for encryption. &lt;em&gt;HMAC&lt;/em&gt; is needed so that adversaries are not able to successfully mutate the ciphertext of the encrypted cookie such that the decrypted version is still semantically valid.&lt;/p&gt;
&lt;p&gt;We also define 2 separate key pairs as one is for &lt;em&gt;Magic Links&lt;/em&gt;, while the other is for the actual encrypted session cookies.&lt;/p&gt;
&lt;p&gt;The expiry of the keys are defined here as well and should match what is stated in the &lt;a href=&quot;https://sh4nnongoh.github.io/blog/3-magic-links/#non-functional-requirements&quot;&gt;Non-Functional requirements&lt;/a&gt;.&lt;/p&gt;
&lt;h4 id=&quot;2-routes&quot;&gt;(2) Routes&lt;/h4&gt;
&lt;p&gt;You may have noticed that secured routes have both a &lt;em&gt;GET&lt;/em&gt; and a &lt;em&gt;POST&lt;/em&gt; method. This is to support URL navigation, whereby the &lt;em&gt;check-auth&lt;/em&gt; page is rendered to capture the &lt;em&gt;CSRF token&lt;/em&gt; in the browser before attempting to retrieve the secured resources with a &lt;em&gt;POST&lt;/em&gt;.&lt;/p&gt;
&lt;h4 id=&quot;3-minimal-javascript&quot;&gt;(3) Minimal Javascript&lt;/h4&gt;
&lt;pre class=&quot;language-javascript&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// Read from meta tag and store in localStorage&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; csrfMeta &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; document&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;querySelector&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;meta[name=&quot;csrf-token&quot;]&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;?.&lt;/span&gt;content&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;csrfMeta&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  localStorage&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;setItem&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;csrfToken&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; csrfMeta&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// Attach CSRF token from meta tag or localstorage to HTMX request&lt;/span&gt;
document&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;addEventListener&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;htmx:configRequest&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;event&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  event&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;detail&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;headers&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;X-CSRF-Token&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;
    csrfMeta &lt;span class=&quot;token operator&quot;&gt;||&lt;/span&gt; localStorage&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getItem&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;csrfToken&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;With &lt;em&gt;HTMX&lt;/em&gt;, there is minimal need to introduce &lt;em&gt;javascript&lt;/em&gt; into our webapp. However, as we will be using the browser&#39;s &lt;em&gt;localstorage&lt;/em&gt; to store the &lt;em&gt;CSRF token&lt;/em&gt;, &lt;em&gt;javascript&lt;/em&gt; is still needed. The above code snippet shows the minimal code needed to store and retrieve the &lt;em&gt;CSRF token&lt;/em&gt;.&lt;/p&gt;
&lt;h4 id=&quot;demo&quot;&gt;Demo&lt;/h4&gt;
&lt;video controls=&quot;&quot; width=&quot;720&quot;&gt;
  &lt;source src=&quot;https://sh4nnongoh.github.io/videos/csrf.mp4&quot; type=&quot;video/mp4&quot;&gt;
  Your browser does not support the video tag.
&lt;/video&gt;
&lt;p&gt;The above video shows the full capabilities of our Magic Link site!&lt;/p&gt;
&lt;div class=&quot;message-box&quot;&gt;
	&lt;p&gt;
    &lt;em&gt;
      Check out the example project here!
      &lt;br&gt;
      &lt;a href=&quot;https://github.com/sh4nnongoh/go-csrf-magic-links&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;
        https://github.com/sh4nnongoh/go-csrf-magic-links
      &lt;/a&gt;
    &lt;/em&gt;
  &lt;/p&gt;
&lt;/div&gt;


</content>
  </entry>
  <entry>
    <title>Magic Links</title>
    <link href="https://sh4nnongoh.github.io/blog/3-magic-links/" />
    <updated>2026-01-19T00:00:00Z</updated>
    <id>https://sh4nnongoh.github.io/blog/3-magic-links/</id>
    <content type="html">&lt;br&gt;
&lt;br&gt;
&lt;div class=&quot;message-box&quot;&gt;
	&lt;p&gt;&lt;em&gt;This is &lt;strong&gt;Part 2&lt;/strong&gt; of the Magic Link System Design Series.&lt;/em&gt;&lt;/p&gt;
  &lt;ol&gt;
    &lt;li&gt;&lt;a href=&quot;https://sh4nnongoh.github.io/blog/2-system-design&quot;&gt;System Design&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;Magic Links&lt;/li&gt;
    &lt;li&gt;&lt;a href=&quot;https://sh4nnongoh.github.io/blog/4-csrf-magic-links&quot;&gt;CSRF with Magic Links&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&quot;https://sh4nnongoh.github.io/blog/5-pprof&quot;&gt;pprof &amp; Load Testing&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&quot;https://sh4nnongoh.github.io/blog/6-pprof-analysis&quot;&gt;pprof Analysis&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&quot;https://sh4nnongoh.github.io/blog/7-pprof-mem&quot;&gt;pprof Memory Optimizations&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&quot;https://sh4nnongoh.github.io/blog/8-pprof-cpu&quot;&gt;pprof CPU&lt;/a&gt;&lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;
&lt;br&gt;
&lt;div class=&quot;message-box&quot;&gt;
	&lt;p&gt;&lt;em&gt;&quot;Hey Shannon! Your previous post talks about Magic Links but there were no details at all about implementing them!&quot;&lt;br&gt;- random reader&lt;/em&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;Hey, I hear you! In the &lt;a href=&quot;https://sh4nnongoh.github.io/blog/2-system-design/&quot;&gt;previous post&lt;/a&gt;, I gave an example System Design writeup for XYZ Auth to implement Magic Links for the organisation. However, remember that System Design documents are living documents, and the previous post was just to highlight the structure of the document.&lt;/p&gt;
&lt;p&gt;In this post we will build upon the System Design in the previous post with details on how Magic Links will be implemented. Specifically, we will create technical artifacts to be placed in the &lt;a href=&quot;https://sh4nnongoh.github.io/blog/2-system-design/#ddd-tactical-design&quot;&gt;Tactical Design&lt;/a&gt; section of the System Design document.&lt;/p&gt;
&lt;div class=&quot;message-box&quot;&gt;
	&lt;p&gt;&lt;em&gt;Magic Links are a mechanism for users to access secure resources without needing to enter passwords.&lt;/em&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;h3 id=&quot;sequence-diagrams&quot;&gt;Sequence Diagrams&lt;/h3&gt;
&lt;p&gt;The best way to explain how Magic Links work is to use Sequence Diagrams.&lt;/p&gt;
&lt;picture&gt;&lt;source type=&quot;image/avif&quot; srcset=&quot;https://sh4nnongoh.github.io/blog/3-magic-links/3HmZXJfn4O-764.avif 764w&quot;&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://sh4nnongoh.github.io/blog/3-magic-links/3HmZXJfn4O-764.webp 764w&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; src=&quot;https://sh4nnongoh.github.io/blog/3-magic-links/3HmZXJfn4O-764.png&quot; alt=&quot;Sequence Diagram&quot; width=&quot;764&quot; height=&quot;767&quot;&gt;&lt;/picture&gt;
&lt;p&gt;The above &lt;a href=&quot;https://www.plantuml.com/plantuml/uml/ZP9FRzGm4CNl_XIZ7k0KSL-Lqj9MN8g4ke9JBrDxIAnDx6Wyfe9FZ_yqQK8s4hTavlt6Rvvz7GHPuj0hrE8PlWTYm00n4AinjQos8pg1Ym-zRwsxo4qSnuVyyuy0etJaKW65J3EYT9FwPjbPKpS3_l4EZlV78gO1RQyC2ZvZ8FZcWxHC8RVCirBP5ZHNimCuLCVaXFYL1l5GlAf9bOX49-qZeQa0a_Piu2Vx0Uu-loalcoP95-Jwi1_OMuD2S5zEUh7IrNcFPTukTykKANAQVuz21cwzFrdQrNyXHvm9XA_OMWqFrfrM-zHL3t0aPnOQ45yClG_Lucgp2jKGy-_Kct9DOyl7OSx8qYyAY_5FJZhsiUtgzDtxqBtLfm3UhTZwX3uDkVJnSWwZqIMCgzqqxgWeD_4zkNVpZVnFb8vUNibj1kLrI6GNDh8wR_M6fprRaW1CnZBfN1OFIGM1T4pLZAaDsfoTDozopk5A-sPqP2_rNARW8sjIr-HC7Fg_&quot;&gt;sequence diagram&lt;/a&gt; shows the happy path of a Magic Link usage.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Users enter their email in the Login page.&lt;/li&gt;
&lt;li&gt;The backend checks if the email exists in the database.&lt;/li&gt;
&lt;li&gt;If the email exists, generate an encrypted cookie detailing who the user is.&lt;/li&gt;
&lt;li&gt;Create a Magic Link with the encrypted cookie as a URL param.&lt;/li&gt;
&lt;li&gt;Send the Magic Link to the user&#39;s email address.&lt;/li&gt;
&lt;li&gt;User clicks the Magic Link, and upon success, gets redirected to the protected page.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;One of the beautiful features of Magic Links is that they use Stateless Cookies. Stateless means that the backend does not need to verify if the content in the Cookie is valid or not; it simply trusts it. This greatly reduces the number of network calls to databases as shown in the sequence diagram above; there is only 1 database call at the beginning, and future visits to protected resources will simply succeed if the Cookie has not expired.&lt;/p&gt;
&lt;div class=&quot;message-box&quot;&gt;
	&lt;p&gt;&lt;em&gt;&quot;But won&#39;t clients just mutate their Cookies to impersonate other people?&quot;&lt;br&gt;- concerned reader&lt;/em&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;In order to prevent manipulation of the Cookie, the Cookie will be encrypted by the server during creation. Only the server has the private key, hence adversaries will not be able to mutate the Cookie to suit their needs. Referring to the &lt;a href=&quot;https://sh4nnongoh.github.io/blog/2-system-design/#system-architecture&quot;&gt;System Architecture&lt;/a&gt; diagram in the previous post, these private encryption keys will be stored in Vercel&#39;s Key-Value stores, such that the backend will have access to them to decrypt / validate incoming requests and their respective Cookies.&lt;/p&gt;
&lt;h3 id=&quot;non-functional-requirements&quot;&gt;Non-Functional Requirements&lt;/h3&gt;
&lt;p&gt;There are security pitfalls associated with Stateless Cookies, and these need to be captured in the &lt;a href=&quot;https://sh4nnongoh.github.io/blog/2-system-design/#non-functional-requirements&quot;&gt;Non-Functional Requirements&lt;/a&gt; of a System Design document.&lt;/p&gt;
&lt;p&gt;Example Additional requirements:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The encryption key needs to be rotated every 7 days.&lt;/li&gt;
&lt;li&gt;The Cookie in the Magic Link should expire within 15 minutes.&lt;/li&gt;
&lt;li&gt;Refreshed Cookies should expire within 60 minutes, before needing a new Magic Link.&lt;/li&gt;
&lt;li&gt;To adopt the &lt;a href=&quot;https://cheatsheetseries.owasp.org/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.html#alternative-using-a-double-submit-cookie-pattern&quot;&gt;Double-Submit Cookie Pattern&lt;/a&gt;, when generating a Cookie.&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&quot;message-box&quot;&gt;
	&lt;p&gt;
    &lt;em&gt;
      Check out my new Go library for creating encrypted Cookies!
      &lt;br&gt;
      &lt;a href=&quot;https://github.com/sh4nnongoh/ironsession&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;
        https://github.com/sh4nnongoh/ironsession
      &lt;/a&gt;
    &lt;/em&gt;
  &lt;/p&gt;
&lt;/div&gt;


</content>
  </entry>
  <entry>
    <title>System Design</title>
    <link href="https://sh4nnongoh.github.io/blog/2-system-design/" />
    <updated>2026-01-16T00:00:00Z</updated>
    <id>https://sh4nnongoh.github.io/blog/2-system-design/</id>
    <content type="html">&lt;br&gt;
&lt;br&gt;
&lt;div class=&quot;message-box&quot;&gt;
	&lt;p&gt;&lt;em&gt;This is &lt;strong&gt;Part 1&lt;/strong&gt; of the Magic Link System Design Series.&lt;/em&gt;&lt;/p&gt;
  &lt;ol&gt;
    &lt;li&gt;&lt;a href=&quot;https://sh4nnongoh.github.io/blog/2-system-design&quot;&gt;System Design&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&quot;https://sh4nnongoh.github.io/blog/3-magic-links&quot;&gt;Magic Links&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&quot;https://sh4nnongoh.github.io/blog/4-csrf-magic-links&quot;&gt;CSRF with Magic Links&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&quot;https://sh4nnongoh.github.io/blog/5-pprof&quot;&gt;pprof &amp; Load Testing&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&quot;https://sh4nnongoh.github.io/blog/6-pprof-analysis&quot;&gt;pprof Analysis&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&quot;https://sh4nnongoh.github.io/blog/7-pprof-mem&quot;&gt;pprof Memory Optimizations&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&quot;https://sh4nnongoh.github.io/blog/8-pprof-cpu&quot;&gt;pprof CPU&lt;/a&gt;&lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;
&lt;p&gt;System Design is such a broad topic, with many different styles adopted by different people. It only became popular recently when it became a requirement during interviews for software engineering roles. This blog is not about tips &amp;amp; tricks for passing half-hour session interviews, but a more realistic take on building systems that lasts.&lt;/p&gt;
&lt;div class=&quot;message-box&quot;&gt;
	&lt;p&gt;&lt;em&gt;The basic study of system design is the understanding of component parts and their subsequent interaction with one another.&lt;br&gt;- Wikipedia&lt;/em&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;Every system is built to solve a problem faced by someone or a business, and people tend to lose sight of that when the team or organisation starts growing. This could be because of how workers are hired for a specific role within a problem but are not directed to solve the business problem. As it is human nature to want to suceed and improve, these individual workers start implementing and improving onto their individual areas in isolation, which Inevidently, results in creating a more complicated and messy system over time.&lt;/p&gt;
&lt;div class=&quot;message-box&quot;&gt;
	&lt;p&gt;&lt;em&gt;The heart of software is its ability to solve domain-related problems for its user.&lt;br&gt;- Eric Evans&lt;/em&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;That is where Domain Driven Design (DDD) comes in, as it brings the problem-solving focus back to the actual issue at hand. It starts by formalizing the language used by the domain-experts and stakeholders, such that engineers can actually use those terminologies during their design and implementation. This solves a huge communication gap between the non-technical and technical folks. As conversations regularly take place between stakeholders, DDD provides a framework for capturing important details in the domain. These details are also commonly known as Objects &amp;amp; Events in the software engineering world (more on that later).&lt;/p&gt;
&lt;p&gt;I will not be diving deep into what DDD is in this blog, but will cherry-pick concepts from it to apply to my approach to System Design.&lt;/p&gt;
&lt;p&gt;To give you a glimpse of what I am talking about, below is a simple System Design document leveraging DDD for building an authentication service for XYZ startup. These System Design documents are living documents that gets updated over time, and what is shown below is just a snapshot in the whole system life cycle.&lt;/p&gt;
&lt;h1 id=&quot;xyz-auth&quot;&gt;XYZ Auth&lt;/h1&gt;
&lt;p&gt;Company XYZ requires a secure way to authenticate its users accessing its app. To keep costs low, and not be subjected to GDPR related policies, passwords cannot be stored within the system. Consulting with the Security Engineer in the team, he advises to use Magic Links as a quick and simple way to authenticate users.&lt;/p&gt;
&lt;h2 id=&quot;table-of-contents&quot;&gt;Table of Contents&lt;/h2&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href=&quot;https://sh4nnongoh.github.io/blog/2-system-design/#ddd-strategic-design&quot;&gt;DDD Strategic Design&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://sh4nnongoh.github.io/blog/2-system-design/#ddd-tactical-design&quot;&gt;DDD Tactical Design&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://sh4nnongoh.github.io/blog/2-system-design/#non-functional-requirements&quot;&gt;Non-Functional Requirements&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://sh4nnongoh.github.io/blog/2-system-design/#api-endpoints&quot;&gt;API Endpoints&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://sh4nnongoh.github.io/blog/2-system-design/#capacity-estimation-(data-storage)&quot;&gt;Capacity Estimation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://sh4nnongoh.github.io/blog/2-system-design/#cost-estimation&quot;&gt;Cost Estimation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://sh4nnongoh.github.io/blog/2-system-design/#system-architecture&quot;&gt;System Architecture&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&quot;system-design&quot;&gt;System Design&lt;/h2&gt;
&lt;hr&gt;
&lt;h3 id=&quot;ddd-strategic-design&quot;&gt;&lt;strong&gt;DDD Strategic Design&lt;/strong&gt;&lt;/h3&gt;
&lt;div class=&quot;message-box&quot;&gt;
	&lt;p&gt;&lt;em&gt;The goal of strategic design is to formalize the language between stakeholders and can be categorized into 3 categories: (1) Events; (2) Objects; (3) Transactions.&lt;/em&gt;&lt;/p&gt;
  &lt;p&gt;&lt;em&gt;Events represent the past and act as the source of truth; they are stored in databases. Objects are models that represent the current state of the domain and are derived from the events that occur over time. Transactions work with objects within the domain to generate events that changes the various objects of the domain.&lt;/em&gt;&lt;/p&gt;
  &lt;p&gt;&lt;em&gt;Conversations need to happen with the Domain Experts, and I personally use a simple Persona table to describe such conversations on what they expect the interaction will be like.&lt;/em&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;The expected interactions with &lt;strong&gt;&lt;code&gt;XYZ Auth&lt;/code&gt;&lt;/strong&gt; are as follows:&lt;/p&gt;
&lt;div class=&quot;simple-table-container&quot;&gt;
  &lt;table class=&quot;simple-table&quot;&gt;
    &lt;thead&gt;
      &lt;tr&gt;
        &lt;th&gt;Persona&lt;/th&gt;
        &lt;th&gt;Interaction&lt;/th&gt;
      &lt;/tr&gt;
    &lt;/thead&gt;
    &lt;tbody&gt;
      &lt;tr&gt;
        &lt;td&gt;User&lt;/td&gt;
        &lt;td&gt;User enters email and requests for Magic Link.&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
        &lt;td&gt;User&lt;/td&gt;
        &lt;td&gt;User clicks on Magic Link and navigates to the Home page of the App.&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
        &lt;td&gt;User&lt;/td&gt;
        &lt;td&gt;User clicks on expired / invalid Magic Link and navigates to the HTTP 401 page of the App.&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
        &lt;td&gt;Admin&lt;/td&gt;
        &lt;td&gt;Admin enters email and requests for Magic Link.&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
        &lt;td&gt;Admin&lt;/td&gt;
        &lt;td&gt;Admin clicks on Magic Link and navigates to the Admin App.&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
        &lt;td&gt;Admin&lt;/td&gt;
        &lt;td&gt;Admin adds Users to the system by entering their emails.&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
        &lt;td&gt;Admin&lt;/td&gt;
        &lt;td&gt;Admin removes Users from the system by deleting their emails.&lt;/td&gt;
      &lt;/tr&gt;
    &lt;/tbody&gt;
  &lt;/table&gt;
&lt;/div&gt;
&lt;p&gt;The domain of &lt;strong&gt;&lt;code&gt;XYZ Auth&lt;/code&gt;&lt;/strong&gt; is as follows:&lt;/p&gt;
&lt;div class=&quot;simple-table-container&quot;&gt;
  &lt;table class=&quot;simple-table&quot;&gt;
    &lt;thead&gt;
      &lt;tr&gt;
        &lt;th&gt;Events&lt;/th&gt;
        &lt;th&gt;Objects&lt;/th&gt;
        &lt;th&gt;Transactions&lt;/th&gt;
      &lt;/tr&gt;
    &lt;/thead&gt;
    &lt;tbody&gt;
      &lt;tr&gt;
        &lt;td&gt;UserAdded&lt;/td&gt;
        &lt;td&gt;User&lt;/td&gt;
        &lt;td&gt;AddUser&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
        &lt;td&gt;UserRemoved&lt;/td&gt;
        &lt;td&gt;&lt;/td&gt;
        &lt;td&gt;RemoveUser&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
        &lt;td&gt;UserRequestsMagicLink&lt;/td&gt;
        &lt;td&gt;&lt;/td&gt;
        &lt;td&gt;RequestMagicLink&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
        &lt;td&gt;UserLogin&lt;/td&gt;
        &lt;td&gt;&lt;/td&gt;
        &lt;td&gt;LoginUser&lt;/td&gt;
      &lt;/tr&gt;
    &lt;/tbody&gt;
  &lt;/table&gt;
&lt;/div&gt;
&lt;h3 id=&quot;ddd-tactical-design&quot;&gt;&lt;strong&gt;DDD Tactical Design&lt;/strong&gt;&lt;/h3&gt;
&lt;div class=&quot;message-box&quot;&gt;
	&lt;p&gt;&lt;em&gt;This section is where a software engineer provides technical artifacts such as ER diagrams or sequence diagrams.&lt;/em&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;br&gt;
&lt;picture&gt;&lt;source type=&quot;image/avif&quot; srcset=&quot;https://sh4nnongoh.github.io/blog/2-system-design/Ntg6bzDa-0-2202.avif 2202w&quot;&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://sh4nnongoh.github.io/blog/2-system-design/Ntg6bzDa-0-2202.webp 2202w&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; src=&quot;https://sh4nnongoh.github.io/blog/2-system-design/Ntg6bzDa-0-2202.png&quot; alt=&quot;ER Diagram&quot; width=&quot;2202&quot; height=&quot;734&quot;&gt;&lt;/picture&gt;
&lt;p&gt;Based on the events and objects identified in the &lt;em&gt;Strategic Design&lt;/em&gt; stage, the above Entity-Relationship diagram is drawn.&lt;/p&gt;
&lt;h3 id=&quot;non-functional-requirements&quot;&gt;&lt;strong&gt;Non-Functional Requirements&lt;/strong&gt;&lt;/h3&gt;
&lt;div class=&quot;message-box&quot;&gt;
	&lt;p&gt;&lt;em&gt;Non-Functional requirements are tricky; and can very often be mixed up with the Domain requirements.&lt;/em&gt;&lt;/p&gt;
	&lt;p&gt;&lt;em&gt;These are very important requirements that are not part of the domain.&lt;/em&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;The Magic Link will only work on the same browser that was used to generate the Magic Link. This is enforced using CSRF tokens.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;api-endpoints&quot;&gt;&lt;strong&gt;API Endpoints&lt;/strong&gt;&lt;/h3&gt;
&lt;div class=&quot;message-box&quot;&gt;
	&lt;p&gt;&lt;em&gt;The endpoints are derived from transactions needed in the Strategic Design phase&lt;/em&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;pre class=&quot;language-bash&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;POST /api/v1/login
POST /api/v1/login?magic&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;string&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
POST /api/v1/users
POST /api/v1/users/&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;id&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
GET /api/v1/users
GET /api/v1/users/&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;id&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;capacity-estimation-data-storage&quot;&gt;&lt;strong&gt;Capacity Estimation&lt;/strong&gt; (Data Storage)&lt;/h3&gt;
&lt;div class=&quot;message-box&quot;&gt;
	&lt;p&gt;&lt;em&gt;Using the ER diagrams described in the Tactical Design stage, provide a back-off-the-envelope estimation of the storage / memory needed for an estimated number of users.&lt;/em&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;Referencing the data structures for &lt;a href=&quot;https://www.postgresql.org/docs/current/datatype.html&quot;&gt;Postgres&lt;/a&gt;, the estimation is as follows:&lt;/p&gt;
&lt;pre class=&quot;language-code&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-code&quot;&gt;id: 16 bytes
event_type: 1 byte * size = 16 bytes
user_id: 16 bytes
created_at: 16 bytes
email: 128 bytes
is_admin: 1 byte&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Hence, an AuthEvent is estimated to be at most &lt;code&gt;(16 + 16 + 16 + 16 + 128 + 1) = 193 bytes&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;With a &lt;code&gt;1GB&lt;/code&gt; Postgres instance, we can store approximately &lt;code&gt;~5.1 million&lt;/code&gt; auth events.&lt;/p&gt;
&lt;h3 id=&quot;cost-estimation&quot;&gt;&lt;strong&gt;Cost Estimation&lt;/strong&gt;&lt;/h3&gt;
&lt;div class=&quot;message-box&quot;&gt;
	&lt;p&gt;&lt;em&gt;Based on the estimates done earlier, you can also estimate the cost of your design. Depending on your service provider, there may be calculators available to estimate the costs of the system.&lt;/em&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;&lt;a href=&quot;https://calculator.aws/#/createCalculator/RDSPostgreSQL&quot;&gt;AWS Calculator&lt;/a&gt;&lt;/p&gt;
&lt;picture&gt;&lt;source type=&quot;image/avif&quot; srcset=&quot;https://sh4nnongoh.github.io/blog/2-system-design/mopT0UT3fV-2616.avif 2616w&quot;&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://sh4nnongoh.github.io/blog/2-system-design/mopT0UT3fV-2616.webp 2616w&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; src=&quot;https://sh4nnongoh.github.io/blog/2-system-design/mopT0UT3fV-2616.png&quot; alt=&quot;Cost&quot; width=&quot;2616&quot; height=&quot;1414&quot;&gt;&lt;/picture&gt;
&lt;h3 id=&quot;system-architecture&quot;&gt;&lt;strong&gt;System Architecture&lt;/strong&gt;&lt;/h3&gt;
&lt;div class=&quot;message-box&quot;&gt;
	&lt;p&gt;&lt;em&gt;This is where the whole architecture of your system is shown. If the system is large, you may add accompanying flow diagrams as well.&lt;/em&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;br&gt;
&lt;picture&gt;&lt;source type=&quot;image/avif&quot; srcset=&quot;https://sh4nnongoh.github.io/blog/2-system-design/uLQ3sDDHv0-2457.avif 2457w&quot;&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://sh4nnongoh.github.io/blog/2-system-design/uLQ3sDDHv0-2457.webp 2457w&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; src=&quot;https://sh4nnongoh.github.io/blog/2-system-design/uLQ3sDDHv0-2457.png&quot; alt=&quot;Architecture&quot; width=&quot;2457&quot; height=&quot;1627&quot;&gt;&lt;/picture&gt;
&lt;hr&gt;


</content>
  </entry>
</feed>