<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <title>Vishnu Bharathi</title>
  
  
  <link href="/atom.xml" rel="self"/>
  
  <link href="https://vishnubharathi.codes/"/>
  <updated>2026-05-20T03:47:53.534Z</updated>
  <id>https://vishnubharathi.codes/</id>
  
  <author>
    <name>Vishnu Bharathi</name>
    
  </author>
  
  <generator uri="http://hexo.io/">Hexo</generator>
  
  <entry>
    <title>Avoiding n+1 with the expand pattern</title>
    <link href="https://vishnubharathi.codes/blog/avoiding-n1-with-the-expand-pattern/"/>
    <id>https://vishnubharathi.codes/blog/avoiding-n1-with-the-expand-pattern/</id>
    <published>2026-05-19T14:27:43.000Z</published>
    <updated>2026-05-20T03:47:53.534Z</updated>
    
    <content type="html"><![CDATA[<p>You might have heard of the n+1 problem in API design. I have taken GraphQL for granted to avoid that problem in the past (and the present).</p><p>Today, I came across a way to avoid it in REST APIs while working with the <a href="https://docs.stripe.com/api">Stripe API</a>. I am naming this the Expand pattern (courtesy of Stripe API Developers). Take this pattern and implement it in your REST APIs to avoid the n+1 problem.</p><h2 id="Problem"><a href="#Problem" class="headerlink" title="Problem"></a>Problem</h2><p>Let us look at a simple API call.</p><figure class="highlight"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">GET /v1/invoices/:invoice-id</span><br></pre></td></tr></table></figure><figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">&#123;</span><br><span class="line">  <span class="attr">&quot;id&quot;</span>: <span class="string">&quot;in_1MtHbELkdIwHu7ixl4OzzPMv&quot;</span>,</span><br><span class="line">  <span class="attr">&quot;object&quot;</span>: <span class="string">&quot;invoice&quot;</span>,</span><br><span class="line">  <span class="attr">&quot;customer&quot;</span>: <span class="string">&quot;cus_NeZwdNtLEOXuvB&quot;</span>,</span><br><span class="line">  <span class="attr">&quot;subscription&quot;</span>: <span class="string">&quot;sub_1MoGGTLkdIwHu7ixZkAA1J0n&quot;</span>,</span><br><span class="line">  <span class="attr">&quot;payment_intent&quot;</span>: <span class="string">&quot;pi_3MtHbELkdIwHu7ix0rUOgsLj&quot;</span>,</span><br><span class="line">  <span class="attr">&quot;amount_due&quot;</span>: <span class="number">5000</span>,</span><br><span class="line">  <span class="attr">&quot;currency&quot;</span>: <span class="string">&quot;usd&quot;</span>,</span><br><span class="line">  <span class="attr">&quot;status&quot;</span>: <span class="string">&quot;open&quot;</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>You usually want to make another request for a field whose ID is present in the response. Let us say we want the customer’s email address. Then we end up making one more API call to get the full customer object.</p><p>This does not look bad for a single invoice. But we usually list things.</p><figure class="highlight"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">GET /v1/invoices</span><br></pre></td></tr></table></figure><figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line">&#123;</span><br><span class="line">  <span class="attr">&quot;object&quot;</span>: <span class="string">&quot;list&quot;</span>,</span><br><span class="line">  <span class="attr">&quot;url&quot;</span>: <span class="string">&quot;/v1/invoices&quot;</span>,</span><br><span class="line">  <span class="attr">&quot;has_more&quot;</span>: <span class="literal">false</span>,</span><br><span class="line">  <span class="attr">&quot;data&quot;</span>: [</span><br><span class="line">    &#123;</span><br><span class="line">      <span class="attr">&quot;id&quot;</span>: <span class="string">&quot;in_1MtHbELkdIwHu7ixl4OzzPMv&quot;</span>,</span><br><span class="line">      <span class="attr">&quot;object&quot;</span>: <span class="string">&quot;invoice&quot;</span>,</span><br><span class="line">      <span class="attr">&quot;customer&quot;</span>: <span class="string">&quot;cus_NeZwdNtLEOXuvB&quot;</span>,</span><br><span class="line">      <span class="attr">&quot;amount_due&quot;</span>: <span class="number">5000</span>,</span><br><span class="line">      <span class="attr">&quot;currency&quot;</span>: <span class="string">&quot;usd&quot;</span>,</span><br><span class="line">      <span class="attr">&quot;status&quot;</span>: <span class="string">&quot;open&quot;</span></span><br><span class="line">    &#125;,</span><br><span class="line">    &#123;</span><br><span class="line">      <span class="attr">&quot;id&quot;</span>: <span class="string">&quot;in_1NaB2cLkdIwHu7ix9Qe3FpzT&quot;</span>,</span><br><span class="line">      <span class="attr">&quot;object&quot;</span>: <span class="string">&quot;invoice&quot;</span>,</span><br><span class="line">      <span class="attr">&quot;customer&quot;</span>: <span class="string">&quot;cus_OpZ1aRtMFQYwxC&quot;</span>,</span><br><span class="line">      <span class="attr">&quot;amount_due&quot;</span>: <span class="number">8200</span>,</span><br><span class="line">      <span class="attr">&quot;currency&quot;</span>: <span class="string">&quot;usd&quot;</span>,</span><br><span class="line">      <span class="attr">&quot;status&quot;</span>: <span class="string">&quot;open&quot;</span></span><br><span class="line">    &#125;</span><br><span class="line">  ]</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>To show the customer’s email for each invoice, we make one more call per invoice. List N invoices and we make N more calls - 1 for the list and N for the customers. That is the n+1 problem.</p><h2 id="Expand-Pattern"><a href="#Expand-Pattern" class="headerlink" title="Expand Pattern"></a>Expand Pattern</h2><p>Stripe provides a param called <a href="https://docs.stripe.com/api/expanding_objects">expand</a> for this on most of its APIs. You can use it to pass the field names that you want to expand. That means you get the full object instead of just the object id.</p><figure class="highlight"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">GET /v1/invoices/:invoice-id?expand[]=customer</span><br></pre></td></tr></table></figure><figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line">&#123;</span><br><span class="line">  <span class="attr">&quot;id&quot;</span>: <span class="string">&quot;in_1MtHbELkdIwHu7ixl4OzzPMv&quot;</span>,</span><br><span class="line">  <span class="attr">&quot;object&quot;</span>: <span class="string">&quot;invoice&quot;</span>,</span><br><span class="line">  <span class="attr">&quot;customer&quot;</span>: &#123;</span><br><span class="line">    <span class="attr">&quot;id&quot;</span>: <span class="string">&quot;cus_NeZwdNtLEOXuvB&quot;</span>,</span><br><span class="line">    <span class="attr">&quot;object&quot;</span>: <span class="string">&quot;customer&quot;</span>,</span><br><span class="line">    <span class="attr">&quot;email&quot;</span>: <span class="string">&quot;jenny.rosen@example.com&quot;</span>,</span><br><span class="line">    <span class="attr">&quot;name&quot;</span>: <span class="string">&quot;Jenny Rosen&quot;</span></span><br><span class="line">  &#125;,</span><br><span class="line">  <span class="attr">&quot;subscription&quot;</span>: <span class="string">&quot;sub_1MoGGTLkdIwHu7ixZkAA1J0n&quot;</span>,</span><br><span class="line">  <span class="attr">&quot;payment_intent&quot;</span>: <span class="string">&quot;pi_3MtHbELkdIwHu7ix0rUOgsLj&quot;</span>,</span><br><span class="line">  <span class="attr">&quot;amount_due&quot;</span>: <span class="number">5000</span>,</span><br><span class="line">  <span class="attr">&quot;currency&quot;</span>: <span class="string">&quot;usd&quot;</span>,</span><br><span class="line">  <span class="attr">&quot;status&quot;</span>: <span class="string">&quot;open&quot;</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>The same works on a list. Expand <code>data.customer</code> and every customer comes back inlined in that single call.</p><figure class="highlight"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">GET /v1/invoices?expand[]=data.customer</span><br></pre></td></tr></table></figure><p>No more N extra calls.</p><h2 id="GraphQL-when"><a href="#GraphQL-when" class="headerlink" title="GraphQL, when?"></a>GraphQL, when?</h2><p>What if I only want the customer’s email and not the whole customer object?</p><p>That doesn’t seem to be possible with expand. It returns all the fields of the expanded object.</p><p>This is the place where we enter the GraphQL territory. GraphQL lets you pick exactly the fields you want. <code>expand</code> only saves you the extra round trip, not the over-fetching cost. But still a good win!</p><h2 id="Nested-Expand"><a href="#Nested-Expand" class="headerlink" title="Nested Expand"></a>Nested Expand</h2><p>It seems like you can do nested expands in the Stripe API like this</p><figure class="highlight"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">GET /v1/invoices/:invoice-id?expand[]=customer.default_source</span><br></pre></td></tr></table></figure><figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line">&#123;</span><br><span class="line">  <span class="attr">&quot;id&quot;</span>: <span class="string">&quot;in_1MtHbELkdIwHu7ixl4OzzPMv&quot;</span>,</span><br><span class="line">  <span class="attr">&quot;object&quot;</span>: <span class="string">&quot;invoice&quot;</span>,</span><br><span class="line">  <span class="attr">&quot;customer&quot;</span>: &#123;</span><br><span class="line">    <span class="attr">&quot;id&quot;</span>: <span class="string">&quot;cus_NeZwdNtLEOXuvB&quot;</span>,</span><br><span class="line">    <span class="attr">&quot;object&quot;</span>: <span class="string">&quot;customer&quot;</span>,</span><br><span class="line">    <span class="attr">&quot;email&quot;</span>: <span class="string">&quot;jenny.rosen@example.com&quot;</span>,</span><br><span class="line">    <span class="attr">&quot;name&quot;</span>: <span class="string">&quot;Jenny Rosen&quot;</span>,</span><br><span class="line">    <span class="attr">&quot;default_source&quot;</span>: &#123;</span><br><span class="line">      <span class="attr">&quot;id&quot;</span>: <span class="string">&quot;card_1NLOFm2eZvKYlo2C8Z9k3K2L&quot;</span>,</span><br><span class="line">      <span class="attr">&quot;object&quot;</span>: <span class="string">&quot;card&quot;</span>,</span><br><span class="line">      <span class="attr">&quot;brand&quot;</span>: <span class="string">&quot;Visa&quot;</span>,</span><br><span class="line">      <span class="attr">&quot;last4&quot;</span>: <span class="string">&quot;4242&quot;</span>,</span><br><span class="line">      <span class="attr">&quot;exp_month&quot;</span>: <span class="number">8</span>,</span><br><span class="line">      <span class="attr">&quot;exp_year&quot;</span>: <span class="number">2026</span></span><br><span class="line">    &#125;</span><br><span class="line">  &#125;,</span><br><span class="line">  <span class="attr">&quot;subscription&quot;</span>: <span class="string">&quot;sub_1MoGGTLkdIwHu7ixZkAA1J0n&quot;</span>,</span><br><span class="line">  <span class="attr">&quot;payment_intent&quot;</span>: <span class="string">&quot;pi_3MtHbELkdIwHu7ix0rUOgsLj&quot;</span>,</span><br><span class="line">  <span class="attr">&quot;amount_due&quot;</span>: <span class="number">5000</span>,</span><br><span class="line">  <span class="attr">&quot;currency&quot;</span>: <span class="string">&quot;usd&quot;</span>,</span><br><span class="line">  <span class="attr">&quot;status&quot;</span>: <span class="string">&quot;open&quot;</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>However, there is a limitation for how deep you can traverse - 4 levels. Still, a deeply nested fetch that would have been several round trips collapses into one call.</p><p>There is no particular reason mentioned for picking 4 as the limit, but if we were to implement the expand pattern in our APIs, we can do something like this. We want a default max depth so a single request cannot fan out forever:</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">Let T &#x3D; number of tables</span><br><span class="line">Let D &#x3D; maximum depth of relations between your tables   (the optimal value)</span><br><span class="line">Let B &#x3D; a higher limit you pick for your app&#39;s use case &#x2F; bandwidth savings</span><br><span class="line"></span><br><span class="line">limit &#x3D; min(D, B),  where  limit &lt; T</span><br></pre></td></tr></table></figure><h2 id="No-worries"><a href="#No-worries" class="headerlink" title="No worries"></a>No worries</h2><p>I think this pattern is useful to know about to avoid overthinking things, like “what if my app becomes a hit overnight and it’s doing a lot of n+1 calls”, “That won’t scale!” etc.</p><p>I am never going to worry about anything like that while building new apps. Just focus on a solid REST API and do the expand pattern - That should give us good mileage.</p>]]></content>
    
    <summary type="html">
    
      
      
        &lt;p&gt;You might have heard of the n+1 problem in API design. I have taken GraphQL for granted to avoid that problem in the past (and the presen
      
    
    </summary>
    
    
      <category term="programming" scheme="https://vishnubharathi.codes/tags/programming/"/>
    
      <category term="api-design" scheme="https://vishnubharathi.codes/tags/api-design/"/>
    
  </entry>
  
  <entry>
    <title>Counting zeros</title>
    <link href="https://vishnubharathi.codes/blog/counting-zeros/"/>
    <id>https://vishnubharathi.codes/blog/counting-zeros/</id>
    <published>2026-04-24T04:44:10.000Z</published>
    <updated>2026-05-20T03:47:53.534Z</updated>
    
    <content type="html"><![CDATA[<p>I have been giving myself the freedom and excuse to explore various software systems in my free time this summer. I am calling this: “Systems Summer”, just so that I take it more seriously, and if anyone asks me what my current side project is, it would be this.</p><p>During that exploration, I realized that there is one underrated skill for an engineer: “counting the number of zeros in a number”.</p><p>There is a cultural element to why I am calling this a skill. It is because all the software-related literature (books, RFCs, design docs, blog posts, papers, etc.) follows the International number system. I am from/in India, where we follow the Indian Number System. The international system is a 2-mark question in our grade/class 1. After that, I moved on to use the Indian number system for almost anything for the next 20 years - that includes all the numbers needed for my algebra, calculus, finance, economics, physics, and chemistry.</p><p>What does that mean?</p><p>Take a look at this number: 1000000 (That’s six zeros if you are counting).</p><ul><li>A person practicing the International Number System<ul><li>would write it as 1,000,000</li><li>would read it as 1 million</li></ul></li><li>A person practicing the Indian Number system<ul><li>would write it as 10,00,000</li><li>would read it as 10 lakhs</li></ul></li></ul><p>I initially struggled to read software literature with numbers. If a blog post says we had 1 million users hit our servers at peak times, I would actually spend a few seconds in my mind trying to convert it and say, “Oh, they had 10 lakh users! That’s great!”</p><p>Once, I was working at a startup where my primary task was to benchmark various KV stores to migrate the system to a store that could handle 10x load. That was my peak number struggling days. I was showing the numbers from a benchmark to the CTO. He sat down with me, and the first thing he started doing was counting zeros. (To my luck, he did it out loud)</p><blockquote><p>1, 2, 3 - That is three zeros, that means a K. So this is 4K bytes.</p></blockquote><p>And he goes,</p><blockquote><p>We have 3… 6 zeros. - That means a million. So this is 4M requests.</p></blockquote><p>That is a turning point for me. Because you can understand things faster that way. I gave up on my “convert to Indian numerals to understand the impact” idea and instead embraced the idea that counting zeros is the way.</p><p>If you ask me how it looks in my brain now. It is as if there are two languages for mathematics. One I use to count money (this is the main use-case for the Indian number system for me), and another one I use to count numbers while working with computers.</p><p>Okay, so this is what you have to remember if you are coming from a similar cultural background:</p><ul><li>Count zeros</li><li>1000<ul><li>3 zeros</li><li>That is a thousand.</li><li>It has another name: Kilo - Kilobyte is one thousand bytes.</li><li>Instagram teenagers mean 4,000 when they say 4k</li><li>= 10<sup>3</sup></li></ul></li><li>1,000,000<ul><li>6 zeros</li><li>That is a million.</li><li>It has another name: Mega - Megabyte is one million bytes.</li><li>If an engineer says you have 1M rows in a table that is not indexed, you are in trouble.</li><li>= 10<sup>6</sup></li></ul></li><li>1,000,000,000<ul><li>9 zeros</li><li>That is a billion</li><li>It is denoted by Giga - Gigabyte is a thousand megabytes i.e., a billion bytes.</li><li>The world population is ~8.3 billion people as of mid-2026.</li><li>= 10<sup>9</sup></li></ul></li></ul><p>~ ~ ~</p><p>That’s enough zeros to get you a good mileage.</p>]]></content>
    
    <summary type="html">
    
      
      
        &lt;p&gt;I have been giving myself the freedom and excuse to explore various software systems in my free time this summer. I am calling this: “Sys
      
    
    </summary>
    
    
      <category term="software" scheme="https://vishnubharathi.codes/tags/software/"/>
    
      <category term="systems-summer" scheme="https://vishnubharathi.codes/tags/systems-summer/"/>
    
      <category term="mathematics" scheme="https://vishnubharathi.codes/tags/mathematics/"/>
    
      <category term="engineering" scheme="https://vishnubharathi.codes/tags/engineering/"/>
    
  </entry>
  
  <entry>
    <title>2025: Year in review</title>
    <link href="https://vishnubharathi.codes/blog/2025-year-in-review/"/>
    <id>https://vishnubharathi.codes/blog/2025-year-in-review/</id>
    <published>2025-12-27T19:32:08.000Z</published>
    <updated>2026-05-20T03:47:53.534Z</updated>
    
    <content type="html"><![CDATA[<p>I’ve always wanted to write a “year in review” blog post, and it’s finally happening here!</p><h2 id="Books"><a href="#Books" class="headerlink" title="Books"></a>Books</h2><p>I read 10 books this year.</p><ul><li><a href="https://www.goodreads.com/book/show/34507927-how-to-take-smart-notes">How to Take Smart Notes</a> - The first book I read this year. It helped me form a note-taking habit. It not only teaches how to take notes but also how to consume knowledge. Highly recommended to anyone.</li><li><a href="https://www.goodreads.com/book/show/39071691-the-bullet-journal-method">The Bullet Journal Method</a> - I picked this up to learn a journaling system. It led me to develop a journaling habit this year. I read it once and re-read parts of it throughout the year to clarify and reinforce certain aspects of the process.</li><li><a href="https://www.goodreads.com/book/show/1319.The_War_of_Art">The War of Art</a> - I discovered this via <a href="https://youtu.be/cpKsogGdem4?si=JjjjfgV8VcAAU0R9">this podcast episode</a> — I paused it midway to get the book. The book introduced me to the idea of resistance (which I discussed <a href="https://vishnubharathi.codes/blog/a-blogger-who-doesnot-blog/">here</a>) that every artist or creative individual faces.</li><li><a href="https://www.goodreads.com/book/show/14912777-turning-pro?from_search=true&amp;from_srp=true&amp;qid=Y4gu7WGOtC&amp;rank=1">Turning Pro</a> - This is a sequel to “The War of Art.” I kept both of these books on my table for a while. Whenever I felt distracted from work, I made myself pick up and read these books instead of doing something else. That usually helped me return to work energized.</li><li><a href="https://www.goodreads.com/book/show/202559882-self-led">Self-Led</a> - This book is about <a href="https://en.wikipedia.org/wiki/Internal_Family_Systems_Model">Internal Family Systems</a>. After reading it, I’ve been observing my “self” and noticing a phenomenon called “Parts Party” (the idea of how one thing leads to another emotionally). Overall, this has made me more self-aware and conscious of how I make others feel. I’m glad I picked up this book earlier this year.</li><li><a href="https://www.goodreads.com/book/show/35051973-dare-to-win">Dare to Win</a> - My daughter randomly chose this book in the bookstore and gave it to me. I took it as a sign from the universe and bought the book. I like reading these kinds of books when I feel low.</li><li><a href="https://www.goodreads.com/book/show/62313346-excellent-advice-for-living">Excellent Advice for Living: Wisdom I Wish I’d Known Earlier</a> - Assorted advice on a variety of things. Loved it!</li><li><a href="https://www.goodreads.com/book/show/17172479-a-little-book-of-life?from_search=true&amp;from_srp=true&amp;qid=bhKBS1BR31&amp;rank=7">A Little Book of Life</a> - Similar to the previous book, but this one is by Ruskin Bond (the author of many stories I’m reading these days to my daughter).</li><li><a href="https://www.goodreads.com/book/show/54898389-the-almanack-of-naval-ravikant?ref=nav_sb_ss_1_12">The Almanack of Naval Ravikant</a> - Soulful. Complete. Clear. This book calmed me down a lot. It had such a positive impact on me that I chose to gift a copy to my sister.</li><li><a href="https://www.goodreads.com/book/show/218272975-coding-interview-patterns?ref=nav_sb_ss_1_25">Coding Interview Patterns</a> - I chose to read this at the start of the year to overcome my anxiety about the job market and job security. A friend recommended it to me. It’s well written and did the job of reducing my anxiety.</li></ul><p>I also started a few more books that I couldn’t complete:</p><ul><li><a href="https://www.goodreads.com/book/show/218272975-coding-interview-patterns?ref=nav_sb_ss_1_25">Four Thousand Weeks</a> - I didn’t complete it, but it still had a great influence on me. I might re-read it from the start if I get the chance.</li><li><a href="https://www.goodreads.com/book/show/55723020-dopamine-nation?from_search=true&amp;from_srp=true&amp;qid=CrVvAMRlLs&amp;rank=1">Dopamine Nation</a> - I have been hearing to some podcasts about dopamine that has made me more mindful about how I spend my energy. I guess I ran out of dopamine to complete this book 😅 I will revisit this book only when I feel like I am misusing my dopamine.</li><li><a href="https://www.goodreads.com/book/show/11797471-the-idea-factory?ac=1&amp;from_search=true&amp;qid=FiUAoju8LL&amp;rank=1">The Idea Factory</a> - This books is about the engineers who worked at Bell Labs (The birthplace of various breakthrough technologies like Transistors, UNIX, C, etc.)</li><li><a href="https://www.goodreads.com/book/show/48581321-api-security-in-action?ref=nav_sb_ss_1_22">API Security in Action</a> - Left halfway because O’Reilly free trial ended ended - lol. But also I found what I was looking for. The thing that completed my journey here was reading through the docs of <a href="https://github.com/ory/hydra">Ory Hydra</a>.</li><li><a href="https://www.goodreads.com/book/show/126571502-postgresql-14-internals?ac=1&amp;from_search=true&amp;qid=sBXJfKOIlh&amp;rank=1">PostgreSQL 14 Internals</a> - My strategy for getting strong with Postgres is to read this book and look at what happened in the future releases of Postgres. It is kind of an intense book and demands certain level of energy.</li></ul><h2 id="Gadgets"><a href="#Gadgets" class="headerlink" title="Gadgets"></a>Gadgets</h2><p>I love trying out and using new gadgets. Here are some gadgets I got this year:</p><ul><li><a href="https://www.lenovo.com/in/en/p/laptops/thinkpad/thinkpadp/thinkpad-p16s-gen-2-16-inch-amd-mobile-workstation/len101t0075?orgRef=https%253A%252F%252Fwww.google.com%252F&amp;srsltid=AfmBOooFjstW_2aJ7f6Rgm3EP2NUqcCRBFKF0oRSvon2o1qrJWK66wny">ThinkPad P16s Gen 2</a> – I received a laptop refresh at work. Previously, I used a Dell XPS 15 and several older ThinkPads, so it was finally time for something new. My personal (and controversial) preference is still the XPS 15 over any ThinkPad. The good thing about ThinkPads is that Ubuntu runs smoothly on them out of the box.</li><li><a href="https://www.oneplus.in/product/oneplus-nord-buds-2r">OnePlus Nord Buds 2r</a> – I got these as a gift. I’ve always preferred wired audio devices—Apple EarPods (wired) have been my primary choice for the past five years. For some reason, I gave these wireless buds a try, and they’ve become my main audio device. I’ve overcome my “wired” obsession because wireless clearly wins in certain situations (for example, wireless is so much better than wired headphones while washing dishes).</li><li><a href="https://www.motorola.in/smartphones-motorola-razr-60/p?skuId=530&amp;srsltid=AfmBOooAUr_elu0FwzmFHN2dhWUfrwJylSnMx0XP1BudmYTQRvs_k9fZ">Moto razr 60</a> – I’ve been using the Moto g82 for the past three years and have wanted to try a foldable phone. I wished for a Samsung Galaxy Z Fold7, but it’s way out of my league price-wise. Hopefully, foldables will become more affordable in the future. I got my hands on the razr 60 in December, so it’s too soon to say much about it.</li><li><a href="https://www.saregama.com/carvaan">Saregama Carvaan</a> – This is my most loved gadget of the year (picture below). It comes loaded with playlists of retro songs. You can often find me carrying this box around the house and playing tunes whenever I feel like it. My favorite playlist is “Top 300.” Overall, I think I listened to more songs on this box than on Spotify this year.</li></ul><p><img width="702" height="575" alt="Pasted image 20251228000227" src="https://github.com/user-attachments/assets/14826472-3658-4d9a-a3bf-a6209fce4dc5" /></p><h2 id="Work"><a href="#Work" class="headerlink" title="Work"></a>Work</h2><ul><li>New title: “Staff Software Engineer” 🎉</li><li>This year marks half a decade with my current employer: <a href="https://hasura.io/">Hasura</a> / <a href="https://promptql.io/">PromptQL</a> and a full decade working at various startups.</li><li>What I have realized over these years is that, there are going to be ups and downs in every org. It is best to focus on learning and getting better and making the most out of our time.</li><li>The essence of my journey had been “show up, ship things, and help others ship” - I like it this way!</li></ul><h2 id="Finance"><a href="#Finance" class="headerlink" title="Finance"></a>Finance</h2><ul><li>🚗 Fixed my car loan.</li><li>💲 Fixed personal loans from the past.</li><li>🏦 Did decent in savings :)</li><li>Doing bad in investments, but it is okay for a guy who had been floating in loans from the past.</li></ul><h2 id="Events"><a href="#Events" class="headerlink" title="Events"></a>Events</h2><p>I showed up at only one in-person tech event this whole year. It was at BLR Go Meetup (Jan) - I helped with getting my employer to be the venue sponsor for this meetup. One thing I loved about this meetup was that they gave the mic to everyone in the room. They have to introduce themselves to the crowd and tell what they are looking to learn out of that meetup. I shared how I discovered Go programming in BMTC (public bus transport of Bangalore) and made a whole bunch of people to laugh/smile. Reflecting back, I feel like that is one of the proudest things I have done in 2025 - putting smiles on faces :)</p><p>I did get a chance to watch the recordings of a few conferences.</p><ul><li><a href="https://www.youtube.com/playlist?list=PLVl2hFL_zAh9DNkmJrGca4mT04f64CHbc">SOSS Days India</a></li><li><a href="https://fosdem.org/2025/schedule/track/go/">FOSDEM 2025 Go Videos</a></li><li>Some <a href="https://www.youtube.com/@GopherConEurope/videos">GopherCon EU 2025</a> videos</li><li>Currently active: <a href="https://www.youtube.com/watch?v=3mvD_Ud7HLY&amp;list=PL2ntRZ1ySWBeBA1lEnmD3vUedkRDvgnmw">GopherCon US 2025</a></li></ul><h2 id="Habits"><a href="#Habits" class="headerlink" title="Habits"></a>Habits</h2><p>Some habits that I formed this year:</p><ul><li>Taking notes while reading books</li><li>Bullet journal</li><li>Drinking coffee in the morning (successfully quit this too — lol :D)</li><li>Drinking tea in the evening (actively in the process of quitting this)</li><li>Switching to warm lighting at night</li><li>Maintaining less than an hour of screen time per day on mobile</li><li>Opening my journal instead of my phone as the first thing in the morning</li></ul><h2 id="Note-Taking"><a href="#Note-Taking" class="headerlink" title="Note Taking"></a>Note Taking</h2><p>I’m proud of my note-taking journey. I blogged about my note-taking setup <a href="https://vishnubharathi.codes/blog/my-note-taking-setup/">here</a> earlier this year. I’ve tweaked it a bit to fit into my bullet journal, but the core principles remain the same.</p><p>All my notes end up in my Obsidian vault. To celebrate my progress, I’m going to share my knowledge graph from Obsidian. This is how it looked around the start of the year:</p><p><img width="1440" height="1321" alt="Pasted image 20251228000250" src="https://github.com/user-attachments/assets/bebfae78-86fc-4263-bc75-83ceb02bde75" /></p><p>And this is how it looks now:</p><p><img width="1028" height="922" alt="Pasted image 20251227235946" src="https://github.com/user-attachments/assets/fc626f87-81f3-4468-b0f9-79db62ddda87" /></p><h2 id="Journals"><a href="#Journals" class="headerlink" title="Journals"></a>Journals</h2><p>This was the biggest productivity experiment I ran throughout the year. I chose bullet journals as my system for journaling. I remixed and adapted a few things, but overall I’m happy with the outcomes.</p><p>One thing I missed in my process was not reflecting enough. I want to improve in that aspect.</p><p>I think the bullet journal book clearly advocates using paper notebooks for journaling (analog). I ran a micro-experiment to go all digital with the help of Obsidian. The outcome: paper wins! I still use Obsidian, but mostly for notes and sometimes as a digital scratchpad. Paper notebooks are a clear winner—they can slow down time for you!</p><p><img width="1236" height="927" alt="Pasted image 20251228001807" src="https://github.com/user-attachments/assets/33ba14fb-137e-4608-be92-5a1738ca8f74" /></p><h2 id="Mantras"><a href="#Mantras" class="headerlink" title="Mantras"></a>Mantras</h2><p>Some things I needed to consciously repeat to myself — hopefully to ingrain them in my behavior:</p><ul><li>Order matters: Brush, Bath, Pray, Eat.</li><li>Do not talk about work with my wife.</li><li>Overcome Resistance.</li><li>Attention residue is real.</li><li>Acquire “Specific Knowledge” every day.</li><li>Calm down and observe the situation. You’ll find a way forward.</li><li>Watch your mood, rest up, and rejuvenate. </li><li>Meditate multiple times a day. Life has tangled so much that one won’t cut it.</li><li>Drop judgments. See what could be good in any situation.</li></ul><p>50% have become second nature to me. I am still working on the rest.</p><h2 id="Side-Projects"><a href="#Side-Projects" class="headerlink" title="Side Projects"></a>Side Projects</h2><p>I tried working on two side projects this year. Both of them flopped, and I had to stop working on them.</p><ul><li><a href="https://github.com/shinobistack/gokakashi">gokakashi</a> – Open source. Built with friends from work (mostly to deploy at work). Stack: Go + Postgres + Vite + React. We had to replace it with something like <a href="https://github.com/hasura/security-agent-tools">this</a>. This is a story in itself with a good deal of learning (saving it for another time).</li><li>A small app I built for my cousin with Next.js + Postgres + Tailwind + shadcn/ui. We had to throw it away because I struggled to find time to make it useful, and my cousin went back to doing things his old way. But this was a valuable learning experience for me. I probably tried out most of the AI-assisted coding tools in the market while working on this project and formed my opinions about them.</li></ul><p>If I have to set a goal for side projects, it would be to build something that stands the test of time.</p><p>~ ~ ~ ~</p><p>Overall, I feel good about all the progress I’ve made this year. I want to keep up the good work and focus on improving!</p>]]></content>
    
    <summary type="html">
    
      
      
        &lt;p&gt;I’ve always wanted to write a “year in review” blog post, and it’s finally happening here!&lt;/p&gt;
&lt;h2 id=&quot;Books&quot;&gt;&lt;a href=&quot;#Books&quot; class=&quot;hea
      
    
    </summary>
    
    
      <category term="life" scheme="https://vishnubharathi.codes/tags/life/"/>
    
      <category term="year-in-review" scheme="https://vishnubharathi.codes/tags/year-in-review/"/>
    
  </entry>
  
  <entry>
    <title>A blogger who doesn&#39;t blog</title>
    <link href="https://vishnubharathi.codes/blog/a-blogger-who-doesnot-blog/"/>
    <id>https://vishnubharathi.codes/blog/a-blogger-who-doesnot-blog/</id>
    <published>2025-11-08T11:54:56.000Z</published>
    <updated>2026-05-20T03:47:53.534Z</updated>
    
    <content type="html"><![CDATA[<p>I recently read this book called <a href="https://www.goodreads.com/book/show/1319.The_War_of_Art">The War of Art</a>. In the book, the author has introduced me to a new idea, which he calls “Resistance”.</p><p>To tell what that is, I must quote a few lines from the book:</p><blockquote><p>Most of us have two lives. The life we live, and the unlived life within us. Between the two stands Resistance…..</p><p>Are you a writer who doesn’t write, a painter who doesn’t paint, an entrepreneur who never starts a venture? Then you know what Resistance is.</p></blockquote><p>The moment I read those lines, I had this realization: “I have become <em>a blogger</em> who doesn’t blog.”</p><p>Today, I want to break that and overcome my resistance to writing blog posts. Because blogging is a soulful act for me. I find it personally rewarding every time I do it, and I always want to do more of it.</p><p>So, here I am! Opening up my journal in the middle of the night to write this blog post on paper to overcome my resistance. “Having to turn on my computer every time I want to write a blog post” has become a resistance for me. Not just that, I am sure there are <code>n</code> different things resisting me at a given point in time. But that is okay - I just need to do better at overcoming them!</p><p>I don’t know why, but I am finding it fun to write this on paper. The words are flowing faster, and I am saving myself from a little bit of screen time.</p><p>I want to do more of this: Resisting my resistance.</p>]]></content>
    
    <summary type="html">
    
      
      
        &lt;p&gt;I recently read this book called &lt;a href=&quot;https://www.goodreads.com/book/show/1319.The_War_of_Art&quot;&gt;The War of Art&lt;/a&gt;. In the book, the a
      
    
    </summary>
    
    
      <category term="life" scheme="https://vishnubharathi.codes/tags/life/"/>
    
  </entry>
  
  <entry>
    <title>First User Framework</title>
    <link href="https://vishnubharathi.codes/blog/first-user-framework/"/>
    <id>https://vishnubharathi.codes/blog/first-user-framework/</id>
    <published>2025-06-04T15:07:03.000Z</published>
    <updated>2026-05-20T03:47:53.537Z</updated>
    
    <content type="html"><![CDATA[<p>I might have accidentally discovered a framework that tries to address work-life balance and side project burnout. For some engineers and builders, this might sound like “common sense”, but it took me a bit of time (a decade - lol) to arrive at this wisdom.</p><p>Here’s the thing: When you have an idea for a project (that light-bulb moment) or when a friend calls you up and says, “Hey, why don’t we build this side project?” your builder instinct kicks in and replies, “Let’s do it!”</p><p>That moment right there is causing a drift in your timeline. I want you to be conscious of that. The thing is, there are only 24 hours in a day, and by signing up to build this new project, you will devote a significant chunk of those hours to it. This might prevent you from doing other activities that are essential for your “work-life balance”.</p><p>How do you find time then? Well, you don’t need to find time for projects. Instead, try finding the right projects for your time.</p><h2 id="Who-is-this-for"><a href="#Who-is-this-for" class="headerlink" title="Who is this for?"></a>Who is this for?</h2><p>Before I continue, I would like to state that this piece of advice is contextual and doesn’t apply to everyone. This advice best applies to you if </p><ul><li>You have a full-time job.</li><li>You are living with your family (and looking to spend your precious evenings with them)</li><li>You are having trouble prioritizing “what to work on”, “what to study”, etc.</li><li>You are having trouble scheduling time.</li><li>You are having constant thoughts of building new projects.</li><li>You sometimes regret spending like 10 hours a week on a project that didn’t go anywhere.</li><li>(I guess you get it)</li></ul><h2 id="The-Framework"><a href="#The-Framework" class="headerlink" title="The Framework"></a>The Framework</h2><p>The truth is, you are building one of these:</p><ul><li>a project with no users</li><li>a project where you are the user</li><li>a project where you have a user (who is not you)</li></ul><p>When you start building a new project, it should fall under one of the above categories. It will eventually lead to one of the following outcomes:</p><ul><li>Best case: Your project is thriving and being used (hopefully by a good number of audience)</li><li>Average case: You hack on your project for a while and eventually forget about it.</li><li>Worst case: You question yourself, “What am I doing with my life?” after weeks/months (hopefully not “years”) of working on the project.</li></ul><p>Just like how most startups go nowhere, I am guessing that most of the side projects don’t hit the best-case outcome. They usually end up in worst or average-case outcomes. From my personal experience, I think I have been part of projects that fall under all (if not most) of the categories and outcomes defined above. Based on that, I have come to the following deduction:</p><table><thead><tr><th>Category</th><th>What you should do</th></tr></thead><tbody><tr><td>No users</td><td>Run away.</td></tr><tr><td>You are the user</td><td>Don’t build it.</td></tr><tr><td>You have a first user</td><td>Build it.</td></tr></tbody></table><blockquote><p><strong>First User Framework</strong>: Start a project only after you have the first user, who is ready to try it out and provide feedback from day 1.</p></blockquote><p> If a category 1 and 2 (no users and you are the user) project seems attractive to you, then challenge yourself to put yourself out there and turn it into category 3 (you have a first user) and then work on it. Instead of taking four months to build a project that no one uses, you will find yourself making meaningful progress in a week if you are able to qualify the project to be category 3 upfront. (we are looking at exponential time gains here; that should be more attractive to you)</p><p>On the other hand, this makes you ruthless about your time and priorities. You might already be working on a short-term goal that is important for you. At times like that, this framework will shine. Either your short-term goal is more important and you pass on the opportunity or this new “category 3” project becomes your short-term goal.</p><h2 id="But-my-passion-project"><a href="#But-my-passion-project" class="headerlink" title="But my passion project?"></a>But my passion project?</h2><p>Usually, passion projects fall under category 1 or 2. So this blog post makes me a villain in the eyes of passion projects. As I mentioned above, this framework is contextual and is written for people who are not finding time and balance in life. If you have the time and freedom to work on a passion project, you should probably do it! There is an immense sense of satisfaction that comes with it.</p><p>For example, I did a category 2 (passion) project: <a href="https://github.com/scriptnull/sblog">a small binary to kick-start my blog writing process</a>. I have been a solo user of it for the past 5 years. I have zero regrets about the time I put into it. So my point is not “don’t work on passion projects”. My point is “Be mindful of your time”.</p><p>~ ~ ~ ~</p><p>“But my friends are calling me to build the next Google?”</p><p>Well, attend the call and ask them, “Where is our first user?”</p>]]></content>
    
    <summary type="html">
    
      
      
        &lt;p&gt;I might have accidentally discovered a framework that tries to address work-life balance and side project burnout. For some engineers and
      
    
    </summary>
    
    
      <category term="career advice" scheme="https://vishnubharathi.codes/tags/career-advice/"/>
    
  </entry>
  
</feed>
