diff --git a/lib/util/http/hooks.ts b/lib/util/http/hooks.ts
new file mode 100644
index 0000000000000000000000000000000000000000..2d6c571627d6552daa3f8b0dc41a234d68cdc5a0
--- /dev/null
+++ b/lib/util/http/hooks.ts
@@ -0,0 +1,25 @@
+// Renovate issue: https://github.com/renovatebot/renovate/issues/12127
+// Got issue: https://github.com/sindresorhus/got/issues/1489
+// From here: https://github.com/sindresorhus/got/issues/1489#issuecomment-805485731
+import type { Hooks, Response } from 'got';
+
+function isResponseOk(response: Response): boolean {
+  const { statusCode } = response;
+  const limitStatusCode = response.request.options.followRedirect ? 299 : 399;
+
+  return (
+    (statusCode >= 200 && statusCode <= limitStatusCode) || statusCode === 304
+  );
+}
+
+export const hooks: Hooks = {
+  afterResponse: [
+    (response: Response): Response => {
+      if (isResponseOk(response)) {
+        response.request.destroy();
+      }
+
+      return response;
+    },
+  ],
+};
diff --git a/lib/util/http/index.ts b/lib/util/http/index.ts
index d9c727ecab81f63f0c4c801bf28079d747f46d03..0dc25d94f381347e3be51f5e3d703987f2f66f80 100644
--- a/lib/util/http/index.ts
+++ b/lib/util/http/index.ts
@@ -8,6 +8,7 @@ import * as memCache from '../cache/memory';
 import { clone } from '../clone';
 import { resolveBaseUrl } from '../url';
 import { applyAuthorization, removeAuthorization } from './auth';
+import { hooks } from './hooks';
 import { applyHostRules } from './host-rules';
 import { getQueue } from './queue';
 import type {
@@ -98,7 +99,7 @@ async function gotRoutine<T>(
 
   // Cheat the TS compiler using `as` to pick a specific overload.
   // Otherwise it doesn't typecheck.
-  const resp = await got<T>(url, options as GotJSONOptions);
+  const resp = await got<T>(url, { ...options, hooks } as GotJSONOptions);
   const duration =
     resp.timings.phases.total || /* istanbul ignore next: can't be tested */ 0;