<?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>Forem: Eugene</title>
    <description>The latest articles on Forem by Eugene (@ineron).</description>
    <link>https://forem.com/ineron</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%2F3871400%2F55375df1-59e1-4269-ab25-6d6c01c50a4e.jpg</url>
      <title>Forem: Eugene</title>
      <link>https://forem.com/ineron</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/ineron"/>
    <language>en</language>
    <item>
      <title>JSON vs JSONB in PostgreSQL: I tested 1M rows to find out</title>
      <dc:creator>Eugene</dc:creator>
      <pubDate>Sun, 12 Apr 2026 07:52:39 +0000</pubDate>
      <link>https://forem.com/ineron/json-vs-jsonb-in-postgresql-i-tested-1m-rows-to-find-ou-3cdj</link>
      <guid>https://forem.com/ineron/json-vs-jsonb-in-postgresql-i-tested-1m-rows-to-find-ou-3cdj</guid>
      <description>&lt;p&gt;Recently I tried to resolve a recurring question in our team:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Is JSON or JSONB actually faster in PostgreSQL?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I couldn’t find a clear answer that matched real-world usage, so I ran my own benchmark.&lt;/p&gt;




&lt;h2&gt;
  
  
  Setup
&lt;/h2&gt;

&lt;p&gt;I loaded &lt;strong&gt;1 million records&lt;/strong&gt; with identical data into both JSON and JSONB columns and tested common operations.&lt;/p&gt;

&lt;p&gt;Hardware:&lt;br&gt;
Dell PowerEdge R450&lt;br&gt;
2x Intel Xeon Silver 4310 (24/48 cores @ 2.1GHz)&lt;/p&gt;

&lt;p&gt;I intentionally used mid-range hardware so the differences would be easier to see.&lt;/p&gt;




&lt;h2&gt;
  
  
  What I tested
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;INSERT performance&lt;/li&gt;
&lt;li&gt;Key-based search (&lt;code&gt;data-&amp;gt;&amp;gt;'field' = 'value'&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Nested updates&lt;/li&gt;
&lt;li&gt;Complex multi-condition queries&lt;/li&gt;
&lt;li&gt;Array access (&lt;code&gt;data-&amp;gt;'items'[0]&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Key existence (&lt;code&gt;data ? 'key'&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Path queries (&lt;code&gt;data #&amp;gt; '{user,profile,name}'&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Aggregations&lt;/li&gt;
&lt;li&gt;Storage size&lt;/li&gt;
&lt;/ul&gt;




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

&lt;h3&gt;
  
  
  Insert speed
&lt;/h3&gt;

&lt;p&gt;JSON was faster:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;JSON: 8.6s&lt;/li&gt;
&lt;li&gt;JSONB: 11.3s&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;~31% difference, which makes sense - JSON is stored as plain text.&lt;/p&gt;




&lt;h3&gt;
  
  
  Query performance
&lt;/h3&gt;

&lt;p&gt;This is where things got interesting.&lt;/p&gt;

&lt;p&gt;JSONB was significantly faster across all read operations:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Simple key extraction → &lt;strong&gt;6.2x faster&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Nested field access → &lt;strong&gt;7.6x faster&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Array operations → &lt;strong&gt;7.3x faster&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Complex conditions → &lt;strong&gt;9.1x faster&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;On average: &lt;strong&gt;~7x faster&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;GIN indexes + binary format make a huge difference here.&lt;/p&gt;




&lt;h3&gt;
  
  
  Updates
&lt;/h3&gt;

&lt;p&gt;For partial updates:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;JSONB was &lt;strong&gt;~71% faster&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  Storage
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;JSON: ~1200 MB&lt;/li&gt;
&lt;li&gt;JSONB: ~888 MB&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;JSONB used &lt;strong&gt;~26% less space&lt;/strong&gt;, mainly due to key deduplication.&lt;/p&gt;




&lt;h2&gt;
  
  
  Key takeaway
&lt;/h2&gt;

&lt;p&gt;If your workload is read-heavy (which is most backend systems):&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;JSONB pays for itself very quickly.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Even with slower inserts, the performance gain in queries dominates after relatively few operations.&lt;/p&gt;




&lt;h2&gt;
  
  
  One important detail
&lt;/h2&gt;

&lt;p&gt;Operators like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;@&amp;gt;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;?&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;?&amp;amp;&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;only work with JSONB.&lt;/p&gt;

&lt;p&gt;Without them, efficient querying becomes very limited.&lt;/p&gt;




&lt;h2&gt;
  
  
  Repo
&lt;/h2&gt;

&lt;p&gt;I published the full benchmark here:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/ineron/postgresql-json-jsonb-benchmark" rel="noopener noreferrer"&gt;https://github.com/ineron/postgresql-json-jsonb-benchmark&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Includes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;SQL scripts&lt;/li&gt;
&lt;li&gt;Python automation&lt;/li&gt;
&lt;li&gt;Docker setup&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Final thought
&lt;/h2&gt;

&lt;p&gt;I expected JSONB to be faster, but not by this margin.&lt;/p&gt;

&lt;p&gt;Curious if anyone has seen similar results in production?&lt;/p&gt;

</description>
      <category>postgressql</category>
      <category>database</category>
      <category>performance</category>
      <category>json</category>
    </item>
  </channel>
</rss>
