diff --git a/app/assets/javascripts/content_editor/extensions/suggestions.js b/app/assets/javascripts/content_editor/extensions/suggestions.js
index e0b6920cf4cedc76c831e98b4e546d0fb21ed4e9..36119209ef3192fc212542d03a1cf168a53e9406 100644
--- a/app/assets/javascripts/content_editor/extensions/suggestions.js
+++ b/app/assets/javascripts/content_editor/extensions/suggestions.js
@@ -54,6 +54,7 @@ function createSuggestionPlugin({
           command: markdownLine.match(/\/\w+/)?.[0],
           cache,
           limit,
+          ...options,
         })
         .search(query);
     },
@@ -158,13 +159,13 @@ export default Node.create({
       });
 
     return [
-      createPlugin('@', 'reference', 'user', { limit: 10 }),
+      createPlugin('@', 'reference', 'user', { limit: 10, filterOnBackend: true }),
       createPlugin('#', 'reference', 'issue'),
       createPlugin('$', 'reference', 'snippet'),
       createPlugin('~', 'referenceLabel', 'label', { limit: 20 }),
       createPlugin('&', 'reference', 'epic'),
       createPlugin('!', 'reference', 'merge_request'),
-      createPlugin('[vulnerability:', 'reference', 'vulnerability'),
+      createPlugin('[vulnerability:', 'reference', 'vulnerability', { filterOnBackend: true }),
       createPlugin('%', 'reference', 'milestone'),
       createPlugin(':', 'emoji', 'emoji'),
       createPlugin('[[', 'link', 'wiki'),
diff --git a/app/assets/javascripts/content_editor/services/autocomplete_helper.js b/app/assets/javascripts/content_editor/services/autocomplete_helper.js
index 66ae4aa1125a994fdce3eb901f125ce02e437ba6..f6b1f7105554761d21cd88d7682c345b677a2937 100644
--- a/app/assets/javascripts/content_editor/services/autocomplete_helper.js
+++ b/app/assets/javascripts/content_editor/services/autocomplete_helper.js
@@ -80,27 +80,26 @@ export function createDataSource({
   sorter = defaultSorter(searchFields),
   cache = true,
   limit = 15,
+  filterOnBackend = false,
 }) {
-  const fetchData = source ? async () => (await axios.get(source)).data : () => [];
-  let items = [];
-
-  const sync = async function sync() {
+  const fetchData = async (query) => {
     try {
-      items = await fetchData();
+      const queryOptions = filterOnBackend ? { params: { search: query } } : {};
+      return source ? (await axios.get(source, queryOptions)).data : [];
     } catch {
-      items = [];
+      return [];
     }
   };
 
   const cacheTimeoutFn = () => (cache ? 0 : Math.floor(Date.now() / 1e4));
-  const init = memoize(sync, cacheTimeoutFn);
+  const memoizedFetchData = memoize(fetchData, cacheTimeoutFn);
 
   return {
     search: async (query) => {
-      await init();
+      let results = filterOnBackend ? await fetchData(query) : await memoizedFetchData();
 
-      let results = items.map(mapper);
-      if (filter) results = filter(items, query);
+      results = results.map(mapper);
+      if (filter) results = filter(results, query);
 
       if (query) {
         results = results.filter((item) => {
@@ -209,8 +208,7 @@ export default class AutocompleteHelper {
       mapper: mappers[referenceType] || mappers.default,
       sorter: sorters[referenceType] || sorters.default,
       filter: filters[referenceType],
-      cache: config.cache,
-      limit: config.limit,
+      ...config,
     });
   };
 }
diff --git a/spec/frontend/content_editor/services/autocomplete_helper_spec.js b/spec/frontend/content_editor/services/autocomplete_helper_spec.js
index 0a4323024a1cb66a404e60ebc57fcd054c9f4946..98ade79eb8b3ef9d6b6aa23b1f96f8f707de88db 100644
--- a/spec/frontend/content_editor/services/autocomplete_helper_spec.js
+++ b/spec/frontend/content_editor/services/autocomplete_helper_spec.js
@@ -74,24 +74,45 @@ describe('createDataSource', () => {
     mock.restore();
   });
 
-  it('fetches data from source and filters based on query', async () => {
-    const data = [
-      { name: 'abc', description: 'xyz' },
-      { name: 'bcd', description: 'wxy' },
-      { name: 'cde', description: 'vwx' },
-    ];
-    mock.onGet('/source').reply(HTTP_STATUS_OK, data);
-
-    const dataSource = createDataSource({
+  describe('on fetch success', () => {
+    const dataSourceParams = {
       source: '/source',
       searchFields: ['name', 'description'],
+    };
+
+    beforeEach(() => {
+      const data = [
+        { name: 'abc', description: 'xyz' },
+        { name: 'bcd', description: 'wxy' },
+        { name: 'cde', description: 'vwx' },
+      ];
+      mock.onGet('/source').reply(HTTP_STATUS_OK, data);
     });
 
-    const results = await dataSource.search('b');
-    expect(results).toEqual([
-      { name: 'bcd', description: 'wxy' },
-      { name: 'abc', description: 'xyz' },
-    ]);
+    it('fetches data from source and filters based on query', async () => {
+      const dataSource = createDataSource(dataSourceParams);
+
+      const results = await dataSource.search('b');
+      expect(results).toEqual([
+        { name: 'bcd', description: 'wxy' },
+        { name: 'abc', description: 'xyz' },
+      ]);
+    });
+
+    describe('if filterOnBackend: true', () => {
+      it('fetches data from source, passing a `search` param', async () => {
+        const dataSource = createDataSource({
+          ...dataSourceParams,
+          filterOnBackend: true,
+        });
+
+        const results = await dataSource.search('bcd');
+        expect(mock.history.get[0].params).toEqual({ search: 'bcd' });
+
+        // results are still filtered out on frontend, on top of backend filtering
+        expect(results).toEqual([{ name: 'bcd', description: 'wxy' }]);
+      });
+    });
   });
 
   it('handles source fetch errors', async () => {