<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Slow but constant memory leak with chrome-pdf recipe on Docker (jsreport 4.12.0)]]></title><description><![CDATA[<p>We are observing a slow but constant memory growth tested on jsreport 4.12.0 running in Docker when generating PDF reports via the chrome-pdf recipe. Memory increases linearly with the number of rendered reports and is never reclaimed, even after extended idle periods.</p>
<p><strong>Environment:</strong><br />
jsreport 4.12.0 (official Docker image jsreport/jsreport:4.12.0)<br />
Docker version 29.1.4-rd<br />
Default configuration (no custom extensions, authentication disabled)<br />
2 Chrome workers (default)</p>
<p><strong>Reproduction steps:</strong><br />
Start the official jsreport container:</p>
<pre><code>docker run -d --name jsreport-memtest -p 15488:5488 \
  -e &quot;extensions_authentication_enabled=false&quot; \
  jsreport/jsreport:4.12.0
</code></pre>
<p>Check initial memory baseline:</p>
<pre><code>docker stats jsreport-memtest --no-stream --format &quot;{{.MemUsage}}&quot;
# ~226 MiB
</code></pre>
<p>Send 500 PDF render requests (100 rounds × 5 parallel) using the script below:</p>
<pre><code># Save as memory-stress-test.sh
for i in $(seq 1 500); do
  curl -s -o /dev/null -X POST http://localhost:15488/api/report \
    -H &quot;Content-Type: application/json&quot; \
    -d '{
      &quot;template&quot;: {
        &quot;content&quot;: &quot;&lt;html&gt;&lt;body&gt;&lt;h1&gt;Memory Test #'$i'&lt;/h1&gt;&lt;table&gt;'$(printf '&lt;tr&gt;&lt;td&gt;Row %s&lt;/td&gt;&lt;td&gt;Value&lt;/td&gt;&lt;td&gt;Lorem ipsum dolor sit amet&lt;/td&gt;&lt;/tr&gt;' $(seq 1 50))'&lt;/table&gt;&lt;/body&gt;&lt;/html&gt;&quot;,
        &quot;engine&quot;: &quot;handlebars&quot;,
        &quot;recipe&quot;: &quot;chrome-pdf&quot;,
        &quot;chrome&quot;: { &quot;landscape&quot;: true, &quot;format&quot;: &quot;A4&quot; }
      }
    }' &amp;
  # Run 5 in parallel, then wait
  if (( i % 5 == 0 )); then
    wait
    sleep 0.5
  fi
done
wait
</code></pre>
<p>Check memory after 500 reports:</p>
<pre><code>docker stats jsreport-memtest --no-stream --format &quot;{{.MemUsage}}&quot;
# ~1062 MiB
</code></pre>
<p>Wait 30 seconds (idle — no requests) and check again:</p>
<pre><code>docker stats jsreport-memtest --no-stream --format &quot;{{.MemUsage}}&quot;
# ~1055 MiB — memory is NOT reclaimed
</code></pre>
<p>Send another 1000 PDF render requests (same script, seq 1 1000) and check:</p>
<pre><code>docker stats jsreport-memtest --no-stream --format &quot;{{.MemUsage}}&quot;
# ~1110 MiB — another +56 MiB that is never reclaimed
</code></pre>
<p>Observed results:</p>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>Phase</th>
<th>Reports rendered</th>
<th>Mem start</th>
<th>Mem end</th>
<th>Delta</th>
</tr>
</thead>
<tbody>
<tr>
<td>Batch 1</td>
<td>500</td>
<td>226 MiB</td>
<td>1062 MiB</td>
<td>+836 MiB</td>
</tr>
<tr>
<td>30s idle</td>
<td>0</td>
<td>1062 MiB</td>
<td>1055 MiB</td>
<td>-7 MiB</td>
</tr>
<tr>
<td>Batch 2</td>
<td>1000</td>
<td>1054 MiB</td>
<td>1110 MiB</td>
<td>+56 MiB</td>
</tr>
<tr>
<td>30s idle</td>
<td>0</td>
<td>1110 MiB</td>
<td>1106 MiB</td>
<td>-4 MiB</td>
</tr>
<tr>
<td>Batch 3</td>
<td>2000</td>
<td>1102 MiB</td>
<td>1225 MiB</td>
<td>+123 MiB</td>
</tr>
</tbody>
</table>
<p>The initial jump (~800 MiB) is mostly Chrome worker startup, which is expected. However, after stabilization, memory continues to grow at approximately +56 MiB per 1000 reports and is never garbage collected.</p>
<p>No zombie processes were found inside the container — this is not a process reaping issue.</p>
<p><strong>Expected behavior:</strong></p>
<p>After rendering is complete, memory should return close to the post-warmup baseline (~1000 MiB), not continue growing indefinitely.</p>
<p><strong>Impact in production on our customer:</strong></p>
<p>In long-running containers that process reports continuously (e.g. scheduled exports every few minutes), this leak accumulates over hours/days and eventually causes OOM kills restarting the Kubernetes pod<br />
<img src="/uploads/files/1776866007516-screenshot-2026-04-22-alle-15.52.56-resized.png" alt="0_1776866005123_Screenshot 2026-04-22 alle 15.52.56.png" class="img-responsive img-markdown" /><br />
<em>4 worker with dedicated-process strategy</em></p>
]]></description><link>https://forum.jsreport.net/topic/3529/slow-but-constant-memory-leak-with-chrome-pdf-recipe-on-docker-jsreport-4-12-0</link><generator>RSS for Node</generator><lastBuildDate>Thu, 23 Apr 2026 14:17:11 GMT</lastBuildDate><atom:link href="https://forum.jsreport.net/topic/3529.rss" rel="self" type="application/rss+xml"/><pubDate>Wed, 22 Apr 2026 14:07:01 GMT</pubDate><ttl>60</ttl><item><title><![CDATA[Reply to Slow but constant memory leak with chrome-pdf recipe on Docker (jsreport 4.12.0) on Invalid Date]]></title><description><![CDATA[<p>We are observing a slow but constant memory growth tested on jsreport 4.12.0 running in Docker when generating PDF reports via the chrome-pdf recipe. Memory increases linearly with the number of rendered reports and is never reclaimed, even after extended idle periods.</p>
<p><strong>Environment:</strong><br />
jsreport 4.12.0 (official Docker image jsreport/jsreport:4.12.0)<br />
Docker version 29.1.4-rd<br />
Default configuration (no custom extensions, authentication disabled)<br />
2 Chrome workers (default)</p>
<p><strong>Reproduction steps:</strong><br />
Start the official jsreport container:</p>
<pre><code>docker run -d --name jsreport-memtest -p 15488:5488 \
  -e &quot;extensions_authentication_enabled=false&quot; \
  jsreport/jsreport:4.12.0
</code></pre>
<p>Check initial memory baseline:</p>
<pre><code>docker stats jsreport-memtest --no-stream --format &quot;{{.MemUsage}}&quot;
# ~226 MiB
</code></pre>
<p>Send 500 PDF render requests (100 rounds × 5 parallel) using the script below:</p>
<pre><code># Save as memory-stress-test.sh
for i in $(seq 1 500); do
  curl -s -o /dev/null -X POST http://localhost:15488/api/report \
    -H &quot;Content-Type: application/json&quot; \
    -d '{
      &quot;template&quot;: {
        &quot;content&quot;: &quot;&lt;html&gt;&lt;body&gt;&lt;h1&gt;Memory Test #'$i'&lt;/h1&gt;&lt;table&gt;'$(printf '&lt;tr&gt;&lt;td&gt;Row %s&lt;/td&gt;&lt;td&gt;Value&lt;/td&gt;&lt;td&gt;Lorem ipsum dolor sit amet&lt;/td&gt;&lt;/tr&gt;' $(seq 1 50))'&lt;/table&gt;&lt;/body&gt;&lt;/html&gt;&quot;,
        &quot;engine&quot;: &quot;handlebars&quot;,
        &quot;recipe&quot;: &quot;chrome-pdf&quot;,
        &quot;chrome&quot;: { &quot;landscape&quot;: true, &quot;format&quot;: &quot;A4&quot; }
      }
    }' &amp;
  # Run 5 in parallel, then wait
  if (( i % 5 == 0 )); then
    wait
    sleep 0.5
  fi
done
wait
</code></pre>
<p>Check memory after 500 reports:</p>
<pre><code>docker stats jsreport-memtest --no-stream --format &quot;{{.MemUsage}}&quot;
# ~1062 MiB
</code></pre>
<p>Wait 30 seconds (idle — no requests) and check again:</p>
<pre><code>docker stats jsreport-memtest --no-stream --format &quot;{{.MemUsage}}&quot;
# ~1055 MiB — memory is NOT reclaimed
</code></pre>
<p>Send another 1000 PDF render requests (same script, seq 1 1000) and check:</p>
<pre><code>docker stats jsreport-memtest --no-stream --format &quot;{{.MemUsage}}&quot;
# ~1110 MiB — another +56 MiB that is never reclaimed
</code></pre>
<p>Observed results:</p>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>Phase</th>
<th>Reports rendered</th>
<th>Mem start</th>
<th>Mem end</th>
<th>Delta</th>
</tr>
</thead>
<tbody>
<tr>
<td>Batch 1</td>
<td>500</td>
<td>226 MiB</td>
<td>1062 MiB</td>
<td>+836 MiB</td>
</tr>
<tr>
<td>30s idle</td>
<td>0</td>
<td>1062 MiB</td>
<td>1055 MiB</td>
<td>-7 MiB</td>
</tr>
<tr>
<td>Batch 2</td>
<td>1000</td>
<td>1054 MiB</td>
<td>1110 MiB</td>
<td>+56 MiB</td>
</tr>
<tr>
<td>30s idle</td>
<td>0</td>
<td>1110 MiB</td>
<td>1106 MiB</td>
<td>-4 MiB</td>
</tr>
<tr>
<td>Batch 3</td>
<td>2000</td>
<td>1102 MiB</td>
<td>1225 MiB</td>
<td>+123 MiB</td>
</tr>
</tbody>
</table>
<p>The initial jump (~800 MiB) is mostly Chrome worker startup, which is expected. However, after stabilization, memory continues to grow at approximately +56 MiB per 1000 reports and is never garbage collected.</p>
<p>No zombie processes were found inside the container — this is not a process reaping issue.</p>
<p><strong>Expected behavior:</strong></p>
<p>After rendering is complete, memory should return close to the post-warmup baseline (~1000 MiB), not continue growing indefinitely.</p>
<p><strong>Impact in production on our customer:</strong></p>
<p>In long-running containers that process reports continuously (e.g. scheduled exports every few minutes), this leak accumulates over hours/days and eventually causes OOM kills restarting the Kubernetes pod<br />
<img src="/uploads/files/1776866007516-screenshot-2026-04-22-alle-15.52.56-resized.png" alt="0_1776866005123_Screenshot 2026-04-22 alle 15.52.56.png" class="img-responsive img-markdown" /><br />
<em>4 worker with dedicated-process strategy</em></p>
]]></description><link>https://forum.jsreport.net/post/14911</link><guid isPermaLink="true">https://forum.jsreport.net/post/14911</guid><dc:creator><![CDATA[l-dalleaste_lectra1]]></dc:creator><pubDate>Invalid Date</pubDate></item><item><title><![CDATA[Reply to Slow but constant memory leak with chrome-pdf recipe on Docker (jsreport 4.12.0) on Invalid Date]]></title><description><![CDATA[<p>This could mean that Chrome or Node.js is just lazy in releasing the memory.<br />
The idle time doesn't necessarily mean the memory gets released.</p>
<p>Try to run the container with limited memory. This should force the memory release.</p>
<pre><code>docker run -d --name jsreport-memtest --memory=500m -p 15488:5488 \
  -e &quot;extensions_authentication_enabled=false&quot; \
  jsreport/jsreport:4.12.0
</code></pre>
<p>With the 500m memory limit, I can run 10 000 reports without OOM.</p>
]]></description><link>https://forum.jsreport.net/post/14912</link><guid isPermaLink="true">https://forum.jsreport.net/post/14912</guid><dc:creator><![CDATA[admin]]></dc:creator><pubDate>Invalid Date</pubDate></item></channel></rss>