diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index da5f9dd8a7..42212452fc 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -208,8 +208,8 @@ jobs:
 
       - name: Memory Leak Test
         run: |
-          node ./scripts/memory/mk.js
-          node ./scripts/memory/index.js
+          node ./scripts/memory/mk.js 
+          node --expose-gc ./scripts/memory/index.js --ci
 
 
   # Changelog can only run _after_ build.
diff --git a/scripts/memory/index.js b/scripts/memory/index.js
index 29b20832dc..067abdc7c0 100644
--- a/scripts/memory/index.js
+++ b/scripts/memory/index.js
@@ -1,87 +1,72 @@
-import { execa } from 'execa';
 import { fileURLToPath } from 'url';
 import v8 from 'v8';
 import dev from '../../packages/astro/dist/core/dev/index.js';
 import { loadConfig } from '../../packages/astro/dist/core/config.js';
 import prettyBytes from 'pretty-bytes';
 
+if (!global.gc) {
+	console.error('ERROR: Node must be run with --expose-gc');
+	process.exit(1);
+}
+
+const isCI = process.argv.includes('--ci');
+
 /** URL directory containing the entire project. */
 const projDir = new URL('./project/', import.meta.url);
 
-function mean(numbers) {
-	var total = 0,
-		i;
-	for (i = 0; i < numbers.length; i += 1) {
-		total += numbers[i];
-	}
-	return total / numbers.length;
-}
-
-function median(numbers) {
-	// median of [3, 5, 4, 4, 1, 1, 2, 3] = 3
-	var median = 0,
-		numsLen = numbers.length;
-	numbers.sort();
-
-	if (
-		numsLen % 2 ===
-		0 // is even
-	) {
-		// average of two middle numbers
-		median = (numbers[numsLen / 2 - 1] + numbers[numsLen / 2]) / 2;
-	} else {
-		// is odd
-		// middle number only
-		median = numbers[(numsLen - 1) / 2];
-	}
-
-	return median;
-}
-
 let config = await loadConfig({
 	cwd: fileURLToPath(projDir),
 });
 
 config.buildOptions.experimentalStaticBuild = true;
 
-const server = await dev(config, { logging: 'error' });
+const server = await dev(config, { logging: { level: 'error' } });
 
 // Prime the server so initial memory is created
 await fetch(`http://localhost:3000/page-0`);
 
-const sizes = [];
-
-function addSize() {
-	sizes.push(v8.getHeapStatistics().total_heap_size);
-}
-
 async function run() {
-	addSize();
 	for (let i = 0; i < 100; i++) {
 		let path = `/page-${i}`;
 		await fetch(`http://localhost:3000${path}`);
 	}
-	addSize();
 }
 
-for (let i = 0; i < 100; i++) {
-	await run();
-}
+global.gc();
+const startSize = v8.getHeapStatistics().used_heap_size;
 
-let lastThirthy = sizes.slice(sizes.length - 30);
-let averageOfLastThirty = mean(lastThirthy);
-let medianOfAll = median(sizes);
-
-// If the trailing average is higher than the median, see if it's more than 5% higher
-if (averageOfLastThirty > medianOfAll) {
-	let percentage = Math.abs(averageOfLastThirty - medianOfAll) / medianOfAll;
-	if (percentage > 0.1) {
-		throw new Error(
-			`The average towards the end (${prettyBytes(averageOfLastThirty)}) is more than 10% higher than the median of all runs (${prettyBytes(
-				medianOfAll
-			)}). This tells us that memory continues to grow and a leak is likely.`
-		);
+// HUMAN mode: Runs forever. Optimized for accurate results on each snapshot Slower than CI.
+if (!isCI) {
+	console.log(`Greetings, human. This test will run forever. Run with the "--ci" flag to finish with a result.`);
+	let i = 1;
+	while (i++) {
+		await run();
+		global.gc();
+		const checkpoint = v8.getHeapStatistics().used_heap_size;
+		console.log(`Snapshot ${String(i).padStart(3, '0')}: ${(checkpoint / startSize) * 100}%`);
 	}
 }
 
+// CI mode: Runs 100 times. Optimized for speed with an accurate final result.
+for (let i = 0; i < 100; i++) {
+	await run();
+	const checkpoint = v8.getHeapStatistics().used_heap_size;
+	console.log(`Estimate ${String(i).padStart(3, '0')}/100: ${(checkpoint / startSize) * 100}%`);
+}
+
+console.log(`Test complete. Running final garbage collection...`);
+global.gc();
+const endSize = v8.getHeapStatistics().used_heap_size;
+
+// If the trailing average is higher than the median, see if it's more than 5% higher
+let percentage = endSize / startSize;
+const TEST_THRESHOLD = 1.2;
+const isPass = percentage < TEST_THRESHOLD;
+console.log(``);
+console.log(`Result: ${isPass ? 'PASS' : 'FAIL'} (${percentage * 100}%)`);
+console.log(`Memory usage began at ${prettyBytes(startSize)} and finished at ${prettyBytes(endSize)}.`);
+console.log(`The threshold for a probable memory leak is ${TEST_THRESHOLD * 100}%`);
+console.log(``);
+console.log(`Exiting...`);
 await server.stop();
+process.exit(isPass ? 0 : 1);