diff --git a/lib/util/minimatch.spec.ts b/lib/util/minimatch.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..5414aacdc765603896f6f4073b61a9949aec5f09
--- /dev/null
+++ b/lib/util/minimatch.spec.ts
@@ -0,0 +1,18 @@
+import { minimatch } from './minimatch';
+
+describe('util/minimatch', () => {
+  it('caches minimatch', () => {
+    expect(minimatch('foo')).toBe(minimatch('foo'));
+    expect(minimatch('foo', { dot: true })).toBe(
+      minimatch('foo', { dot: true })
+    );
+  });
+
+  it('does not cache minimatch', () => {
+    expect(minimatch('foo', undefined, false)).not.toBe(
+      minimatch('foo', undefined, false)
+    );
+    expect(minimatch('foo')).not.toBe(minimatch('foo', undefined, false));
+    expect(minimatch('foo', { dot: true })).not.toBe(minimatch('foo'));
+  });
+});
diff --git a/lib/util/minimatch.ts b/lib/util/minimatch.ts
new file mode 100644
index 0000000000000000000000000000000000000000..0d915d8be909bdd2cee4341b24b1f002c2941051
--- /dev/null
+++ b/lib/util/minimatch.ts
@@ -0,0 +1,24 @@
+import { Minimatch, MinimatchOptions } from 'minimatch';
+
+const cache = new Map<string, Minimatch>();
+
+export function minimatch(
+  pattern: string,
+  options?: MinimatchOptions,
+  useCache = true
+): Minimatch {
+  const key = options ? `${pattern}:${JSON.stringify(options)}` : pattern;
+
+  if (useCache) {
+    const cachedResult = cache.get(key);
+    if (cachedResult) {
+      return cachedResult;
+    }
+  }
+
+  const instance = new Minimatch(pattern, options);
+  if (useCache) {
+    cache.set(key, instance);
+  }
+  return instance;
+}