diff --git a/lib/utils/fetch-utils.js b/lib/utils/fetch-utils.js
new file mode 100644
--- /dev/null
+++ b/lib/utils/fetch-utils.js
@@ -0,0 +1,56 @@
+// @flow
+
+type RequestWithTimeoutOptions = {
+  ...$Exact<RequestOptions>,
+  +timeout?: number, // ms
+};
+
+async function fetchWithTimeout(
+  url: string,
+  options?: RequestWithTimeoutOptions,
+): Promise<Response> {
+  const { timeout, signal: externalSignal, ...requestOptions } = options || {};
+
+  const abortController = new AbortController();
+
+  // Handle situation when callee has abort signal already set
+  let externalAbort = false;
+  const externalAbortEvent = () => {
+    externalAbort = true;
+    abortController.abort();
+  };
+  if (externalSignal) {
+    if (externalSignal.aborted) {
+      externalAbortEvent();
+    } else {
+      externalSignal.addEventListener('abort', externalAbortEvent);
+    }
+  }
+
+  let timeoutHandle;
+  if (timeout) {
+    timeoutHandle = setTimeout(() => {
+      abortController.abort();
+    }, timeout);
+  }
+
+  try {
+    return await fetch(url, {
+      ...requestOptions,
+      signal: abortController.signal,
+    });
+  } catch (err) {
+    if (abortController.signal.aborted && !externalAbort) {
+      throw new Error('Request timed out');
+    } else {
+      throw err;
+    }
+  } finally {
+    clearTimeout(timeoutHandle);
+    if (externalSignal) {
+      externalSignal.removeEventListener('abort', externalAbortEvent);
+    }
+  }
+}
+
+export { fetchWithTimeout };
diff --git a/lib/utils/reports-service.js b/lib/utils/reports-service.js
--- a/lib/utils/reports-service.js
+++ b/lib/utils/reports-service.js
@@ -1,5 +1,6 @@
 // @flow
 
+import { fetchWithTimeout } from './fetch-utils.js';
 import {
   reportsServiceURL,
   sendReportEndpoint,
@@ -9,6 +10,8 @@
   ReportsServiceSendReportsResponse,
 } from '../types/report-types.js';
 
+const REQUEST_TIMEOUT = 60 * 1000; // 60s
+
 async function sendReports(
   reports: ReportsServiceSendReportsRequest,
 ): Promise<ReportsServiceSendReportsResponse> {
@@ -23,12 +26,13 @@
     return report;
   });
   const url = `${reportsServiceURL}${sendReportEndpoint.path}`;
-  const response = await fetch(url, {
+  const response = await fetchWithTimeout(url, {
     method: sendReportEndpoint.method,
     body: JSON.stringify(requestBody),
     headers: {
       'Content-Type': 'application/json',
     },
+    timeout: REQUEST_TIMEOUT,
   });
 
   if (!response.ok) {