title: Why does the heap size limit readjust to larger size in nodejs during a memory leak instead of crashing?
body: <p>I was trying to recreate a <code>FATAL ERROR: Reached heap limit Allocation failed - JavaScript heap out of memory</code> that I get in production on heroku.</p>
  <p>But my local machine will readjust the heap limit.</p>
  <p>If I set the heap size limit <code>node --max-old-space-size=200 ./bin/www.js</code> the limit seems to readjust as I near it. It goes from around 200mb to over 800mb. I would expect it to stay at 200mb and crash. Why does this happen?</p>
  <p>Reproduced memory leak</p>
  <pre class="lang-js prettyprint-override"><code>const crashArray = [];
  ...
   app.get('/leak', async (req, res, next) =&gt; {
      v8Print('before push to array');
      crashArray.push(...Array(0.12e6).fill('some string'));
      crashArray.push(...Array(0.12e6).fill('some string'));
      crashArray.push(...Array(0.12e6).fill('some string'));
      crashArray.push(...Array(0.12e6).fill('some string'));
      crashArray.push(...Array(0.12e6).fill('some string'));
      crashArray.push(...Array(0.12e6).fill('some string'));
  
      v8Print('after push to array');
  
      res.sendStatus(200);
    });
  </code></pre>
  <p>Log function</p>
  <pre class="lang-js prettyprint-override"><code>const v8 = require('v8');
  
  // for memory allocation heap debugging
  module.exports.v8Print = (message) =&gt; {
    const heapStats = v8.getHeapStatistics();
    const heapStatsMB = heapStats;
    for (const key in heapStatsMB) {
      heapStatsMB[key] = `${(((heapStatsMB[key] / 1024 / 1024) * 100) / 100).toFixed(2)} MB`;
    }
    console.log('');
    console.log(message);
    console.table(heapStatsMB);
    console.log('');
  };
  
  </code></pre>
  <p>I call the GET <code>/leak</code> request a bunch of times to reproduce a leak. When I get close the heap limit adjusts.</p>
  <pre><code>before push to array
  ┌─────────────────────────────┬─────────────┐
  │           (index)           │   Values    │
  ├─────────────────────────────┼─────────────┤
  │       total_heap_size       │ '155.28 MB' │
  │ total_heap_size_executable  │  '0.80 MB'  │
  │     total_physical_size     │ '154.35 MB' │
  │    total_available_size     │ '122.37 MB' │
  │       used_heap_size        │ '114.22 MB' │
  │       heap_size_limit       │ '248.00 MB' │
  │       malloced_memory       │  '0.01 MB'  │
  │    peak_malloced_memory     │  '2.10 MB'  │
  │      does_zap_garbage       │  '0.00 MB'  │
  │  number_of_native_contexts  │  '0.00 MB'  │
  │ number_of_detached_contexts │  '0.00 MB'  │
  └─────────────────────────────┴─────────────┘
  
  
  after push to array
  ┌─────────────────────────────┬─────────────┐
  │           (index)           │   Values    │
  ├─────────────────────────────┼─────────────┤
  │       total_heap_size       │ '169.45 MB' │
  │ total_heap_size_executable  │  '0.80 MB'  │
  │     total_physical_size     │ '168.53 MB' │
  │    total_available_size     │ '175.61 MB' │
  │       used_heap_size        │ '128.00 MB' │
  │       heap_size_limit       │ '848.00 MB' │ // &lt;----- heap size limit changes
  │       malloced_memory       │  '0.01 MB'  │
  │    peak_malloced_memory     │  '2.10 MB'  │
  │      does_zap_garbage       │  '0.00 MB'  │
  │  number_of_native_contexts  │  '0.00 MB'  │
  │ number_of_detached_contexts │  '0.00 MB'  │
  └─────────────────────────────┴─────────────┘
  </code></pre>