<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Ahmad Fauzan Alghifari</title>
    <description>The latest articles on DEV Community by Ahmad Fauzan Alghifari (@fazghfr).</description>
    <link>https://dev.to/fazghfr</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3877662%2F0534252a-653d-417d-9e10-e1ce5a6194b2.jpeg</url>
      <title>DEV Community: Ahmad Fauzan Alghifari</title>
      <link>https://dev.to/fazghfr</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/fazghfr"/>
    <language>en</language>
    <item>
      <title>The latest() Bug That Silently Duplicated Transaction IDs in Production</title>
      <dc:creator>Ahmad Fauzan Alghifari</dc:creator>
      <pubDate>Mon, 20 Apr 2026 02:05:56 +0000</pubDate>
      <link>https://dev.to/fazghfr/the-latest-bug-that-silently-duplicated-transaction-ids-in-production-42ip</link>
      <guid>https://dev.to/fazghfr/the-latest-bug-that-silently-duplicated-transaction-ids-in-production-42ip</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;TL;DR:&lt;/strong&gt; Using &lt;code&gt;Model::latest()-&amp;gt;first()&lt;/code&gt; to get the "latest" record by ID is wrong. &lt;code&gt;latest()&lt;/code&gt; orders by &lt;code&gt;created_at&lt;/code&gt;, not by the value of your ID column. When two rows are inserted within the same second, both reads return the same record, and you get duplicate IDs.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Background
&lt;/h2&gt;

&lt;p&gt;I built a simple sequential ID generator for transaction IDs. The logic was straightforward: fetch the latest record, read its code, increment the number, return the next one.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nv"&gt;$start&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"XX00000001"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nv"&gt;$latest&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Model&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;latest&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;first&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nv"&gt;$latest&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nv"&gt;$latest&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;code&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nv"&gt;$start&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nv"&gt;$value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$latest&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;code&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nb"&gt;preg_match&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'/^XX\d{8}$/'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$value&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nv"&gt;$start&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nv"&gt;$num&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nb"&gt;substr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s2"&gt;"XX"&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt; &lt;span class="nb"&gt;str_pad&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$num&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;STR_PAD_LEFT&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It worked. Passed local and dev branch testing. Got merged into production with no issues. Then one day, a user reported duplicate IDs on different transactions.&lt;/p&gt;




&lt;h2&gt;
  
  
  So What Happened?
&lt;/h2&gt;

&lt;p&gt;My assumption was that &lt;code&gt;latest()&lt;/code&gt; would always return the record with the highest ID. Logically, the latest record should have the highest code, right?&lt;/p&gt;

&lt;p&gt;Wrong. &lt;code&gt;latest()&lt;/code&gt; in Laravel is just a shorthand for &lt;code&gt;orderBy('created_at', 'desc')&lt;/code&gt;. It doesn't care about your ID column, it orders by &lt;code&gt;created_at&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;This means the correctness of the whole function depends entirely on &lt;code&gt;created_at&lt;/code&gt; being precise enough to differentiate between records. And it wasn't.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;created_at&lt;/code&gt; column was storing timestamps in &lt;code&gt;DD:MM:YY hh:mm:ss&lt;/code&gt; format. The smallest unit is &lt;strong&gt;seconds&lt;/strong&gt;. If two rows are inserted within the same second — whether by two users simultaneously, or by a backend loop calling this function in rapid succession, both calls to &lt;code&gt;latest()-&amp;gt;first()&lt;/code&gt; return the same record. Both read the same code. Both return the same next ID.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;created_at&lt;/th&gt;
&lt;th&gt;ID generated&lt;/th&gt;
&lt;th&gt;note&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;20:04:01&lt;/td&gt;
&lt;td&gt;XX00000001&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;20:04:01&lt;/td&gt;
&lt;td&gt;XX00000002&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;20:04:01&lt;/td&gt;
&lt;td&gt;XX00000002&lt;/td&gt;
&lt;td&gt;DUPLICATE&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;20:04:01&lt;/td&gt;
&lt;td&gt;XX00000002&lt;/td&gt;
&lt;td&gt;DUPLICATE&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;20:04:02&lt;/td&gt;
&lt;td&gt;XX00000003&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;20:04:02&lt;/td&gt;
&lt;td&gt;XX00000003&lt;/td&gt;
&lt;td&gt;DUPLICATE&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The bug wasn't in the increment logic. It was in the assumption that "latest by time" equals "latest by value."&lt;/p&gt;




&lt;h2&gt;
  
  
  The Fix
&lt;/h2&gt;

&lt;p&gt;Instead of relying on &lt;code&gt;created_at&lt;/code&gt; ordering, query for the actual maximum code value directly.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nv"&gt;$start&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"XX00000001"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nv"&gt;$maxValue&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Model&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;where&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'code'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'LIKE'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'XX%'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nb"&gt;max&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'code'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nv"&gt;$maxValue&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nv"&gt;$start&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nv"&gt;$num&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nb"&gt;substr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$maxValue&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nv"&gt;$next&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$num&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s2"&gt;"XX"&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt; &lt;span class="nb"&gt;str_pad&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$next&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;STR_PAD_LEFT&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;max('code')&lt;/code&gt; operates on the actual data value, not on metadata like &lt;code&gt;created_at&lt;/code&gt;. Regardless of when a record was inserted, this always returns the highest code in the table, which is exactly what we need.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;One thing worth noting:&lt;/strong&gt; this fix doesn't eliminate the race condition entirely. Two requests can still call this function simultaneously, both read the same &lt;code&gt;max&lt;/code&gt; before either one writes. For a truly bulletproof solution, you'd want a database-level lock (&lt;code&gt;SELECT FOR UPDATE&lt;/code&gt;), a &lt;code&gt;UNIQUE&lt;/code&gt; constraint on the column to let the DB reject duplicates, or just use &lt;code&gt;AUTO_INCREMENT&lt;/code&gt; and format on read. The &lt;code&gt;max()&lt;/code&gt; fix is a significant improvement, but it's not atomic. &lt;/p&gt;




&lt;h2&gt;
  
  
  What I Should Have Done
&lt;/h2&gt;

&lt;p&gt;Looking back, there were two things that would have caught this before it hit production.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Write automated tests that simulate concurrent calls.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The bug was triggered by calling this function inside a loop — something that can't be reproduced through the UI or by a non-technical tester. A simple test that calls the function in a loop ten times and asserts all returned IDs are unique would have caught this immediately.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Look at the database earlier.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I spent too long staring at the code when the code itself was innocent. The real issue was in the data structure — specifically, the precision of the &lt;code&gt;created_at&lt;/code&gt; column. Checking the actual column type and sample data earlier would have pointed me in the right direction much faster.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;The most frustrating bugs are the ones where the code does exactly what you told it to. The problem is what you assumed it would do.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>timestamp</category>
      <category>laravel</category>
      <category>backend</category>
      <category>sql</category>
    </item>
    <item>
      <title>How I Fixed a Correlated Subquery That Was Behaving Like an N+1 Problem in Production</title>
      <dc:creator>Ahmad Fauzan Alghifari</dc:creator>
      <pubDate>Tue, 14 Apr 2026 07:36:39 +0000</pubDate>
      <link>https://dev.to/fazghfr/how-i-fixed-a-correlated-subquery-that-was-behaving-like-an-n1-problem-in-production-abn</link>
      <guid>https://dev.to/fazghfr/how-i-fixed-a-correlated-subquery-that-was-behaving-like-an-n1-problem-in-production-abn</guid>
      <description>&lt;h2&gt;
  
  
  What Happened
&lt;/h2&gt;

&lt;p&gt;A user reported seeing no data after an absurdly long loading time in one of the procurement menus. I was maintaining an e-procurement system for a state-owned enterprise subsidiary in the mining sector and this wasn't just a UI glitch. It completely blocked the user's business process. &lt;/p&gt;

&lt;p&gt;From the network tab, the problematic request was just sitting there with endless pending status, until it hit the server's timeout and resulted in 504, effectively sending no data to the user.&lt;/p&gt;

&lt;p&gt;The culprit turned out to be a correlated subquery behaving exactly like an N+1 problem: common, easy to miss, and quietly fatal in production. In this post, I'll walk through how I identified the root cause and fixed it.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is an N+1 Query Problem?
&lt;/h2&gt;

&lt;p&gt;Imagine you have to fetch 500 data from the database. And then, for each of that row, you run another query to compute something like aggregations. That's 1 (the initial fetching) query plus 500 query for each computation. In production, because the data will keep growing, this would be a fatal problem.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="c1"&gt;// CLASSIC ORM N+1 EXAMPLE&lt;/span&gt;
&lt;span class="c1"&gt;// 1 query&lt;/span&gt;
&lt;span class="nv"&gt;$orders&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Order&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;all&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="c1"&gt;// N queries — one per order&lt;/span&gt;
&lt;span class="k"&gt;foreach&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$orders&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nv"&gt;$order&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="nv"&gt;$order&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;supplier&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// hits the database every single iteration&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This commonly happens when we use ORM loops like in laravel. But N+1 problem does not happen only to ORMs. Something similar could also happen to the database query itself. Which is exactly what happened in my case.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Actually Happened
&lt;/h2&gt;

&lt;p&gt;This is a snippet of a long scope code that was implemented with laravel.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;select&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;span class="mf"&gt;...&lt;/span&gt;
&lt;span class="k"&gt;CASE&lt;/span&gt; &lt;span class="no"&gt;WHEN&lt;/span&gt; &lt;span class="nb"&gt;COUNT&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;po_items&lt;/span&gt;&lt;span class="mf"&gt;.&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="nf"&gt;THEN&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;SELECT&lt;/span&gt; &lt;span class="nf"&gt;SUM&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;total_value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
     &lt;span class="no"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;po_items&lt;/span&gt;
     &lt;span class="no"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;po_items&lt;/span&gt;&lt;span class="mf"&gt;.&lt;/span&gt;&lt;span class="n"&gt;po_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;po&lt;/span&gt;&lt;span class="mf"&gt;.&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; 
  &lt;span class="no"&gt;END&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;sum_val&lt;/span&gt;
&lt;span class="mf"&gt;...&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Do you see the problem? Yup. Its computing an aggregation function SUM() within the select statement. So for each data that comes from the &lt;code&gt;FROM&lt;/code&gt; keyword, let's assume we have 1000 rows, it will run that exact SUM() query for another 1000 times. This will work on small data, but in production environment and database, this query won't survive.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Fix
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;leftjoin&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="n"&gt;po_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="k"&gt;SUM&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;total_value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;sum_val&lt;/span&gt;
  &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;po_items&lt;/span&gt;
  &lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;status&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'y'&lt;/span&gt;
  &lt;span class="k"&gt;GROUP&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt; &lt;span class="n"&gt;po_id&lt;/span&gt; 
&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;po_item_aggs&lt;/span&gt; &lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="n"&gt;po&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;po_item_aggs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;po_id&lt;/span&gt;

&lt;span class="c1"&gt;-- accessing it directly&lt;/span&gt;
&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="n"&gt;po&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;po_item_aggs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sum_val&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is what I did. Instead of doing the aggregations and the subquery inside the select statement, I moved it into another Join operations. This alone removes the computation for each row from the data source. So instead of doing 1000+ query computation, we only did one query for the computation itself.&lt;/p&gt;

&lt;h2&gt;
  
  
  Results
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqci5m53juvglfp2fu37w.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqci5m53juvglfp2fu37w.png" alt="Before fix — request pending, 504 timeout" width="418" height="206"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzuyo8e2wve16229d7h8v.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzuyo8e2wve16229d7h8v.png" alt="After fix — request resolves normally" width="241" height="182"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Metric&lt;/th&gt;
&lt;th&gt;Before&lt;/th&gt;
&lt;th&gt;After&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Response time&lt;/td&gt;
&lt;td&gt;~2 minutes / timeout&lt;/td&gt;
&lt;td&gt;~15 seconds&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;HTTP status&lt;/td&gt;
&lt;td&gt;504 Gateway Timeout&lt;/td&gt;
&lt;td&gt;200 OK&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;User experience&lt;/td&gt;
&lt;td&gt;Blank table, blocked workflow&lt;/td&gt;
&lt;td&gt;Normal&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The request that was hanging for over two minutes — or not returning at all — now resolves in around 15 seconds. That's not just a performance improvement, it's the difference between a system that works and one that doesn't.&lt;/p&gt;

</description>
      <category>laravel</category>
      <category>backend</category>
      <category>sql</category>
      <category>postgres</category>
    </item>
  </channel>
</rss>
