diff --git a/Gemfile b/Gemfile
index 9520fe8148133e53e15563214242a1b418d86330..6611c009483b18c01ad95b174611fa42514ca1d2 100644
--- a/Gemfile
+++ b/Gemfile
@@ -86,7 +86,7 @@ gem 'grape-entity', '~> 0.7.1'
 gem 'rack-cors', '~> 1.0.0', require: 'rack/cors'
 
 # GraphQL API
-gem 'graphql', '= 1.8.4'
+gem 'graphql', '= 1.8.17'
 gem 'graphiql-rails', '~> 1.4.10'
 gem 'apollo_upload_server', '~> 2.0.0.beta3'
 gem 'graphql-docs', '~> 1.6.0', group: [:development, :test]
diff --git a/Gemfile.lock b/Gemfile.lock
index 58d399c5d48055d2263df2e59a3e514b934e92e6..c78a6f29fbefcfc8034b4afb64e23d37f0d63442 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -402,7 +402,7 @@ GEM
     graphiql-rails (1.4.10)
       railties
       sprockets-rails
-    graphql (1.8.4)
+    graphql (1.8.17)
     graphql-docs (1.6.0)
       commonmarker (~> 0.16)
       escape_utils (~> 1.2)
@@ -1146,7 +1146,7 @@ DEPENDENCIES
   grape-path-helpers (~> 1.1)
   grape_logging (~> 1.7)
   graphiql-rails (~> 1.4.10)
-  graphql (= 1.8.4)
+  graphql (= 1.8.17)
   graphql-docs (~> 1.6.0)
   grpc (~> 1.19.0)
   gssapi
diff --git a/app/graphql/mutations/notes/create/base.rb b/app/graphql/mutations/notes/create/base.rb
index d3a5dae21881ba80cdf70ce4884779fe3862f40c..cf9f74a63d8d17093065c4de3b57faca67e8dc18 100644
--- a/app/graphql/mutations/notes/create/base.rb
+++ b/app/graphql/mutations/notes/create/base.rb
@@ -18,8 +18,6 @@ module Mutations
                   required: true,
                   description: copy_field_description(Types::Notes::NoteType, :body)
 
-        private
-
         def resolve(args)
           noteable = authorized_find!(id: args[:noteable_id])
 
@@ -37,6 +35,8 @@ module Mutations
           }
         end
 
+        private
+
         def create_note_params(noteable, args)
           {
             noteable: noteable,
diff --git a/app/graphql/resolvers/full_path_resolver.rb b/app/graphql/resolvers/full_path_resolver.rb
index 972f318c8065ab8eb3f22adae9ac60c44c48c313..2afd0411ea6c071eb283b31974c07aa9b5cff927 100644
--- a/app/graphql/resolvers/full_path_resolver.rb
+++ b/app/graphql/resolvers/full_path_resolver.rb
@@ -11,7 +11,7 @@ module Resolvers
     end
 
     def model_by_full_path(model, full_path)
-      BatchLoader.for(full_path).batch(key: model) do |full_paths, loader, args|
+      BatchLoader::GraphQL.for(full_path).batch(key: model) do |full_paths, loader, args|
         # `with_route` avoids an N+1 calculating full_path
         args[:key].where_full_path_in(full_paths).with_route.each do |model_instance|
           loader.call(model_instance.full_path, model_instance)
diff --git a/app/graphql/resolvers/issues_resolver.rb b/app/graphql/resolvers/issues_resolver.rb
index 6988b451ec35f43220f95f041cd1bb938f213a40..dd104e83f43715308fd17a5cc996e264c736cbf5 100644
--- a/app/graphql/resolvers/issues_resolver.rb
+++ b/app/graphql/resolvers/issues_resolver.rb
@@ -41,13 +41,11 @@ module Resolvers
 
     type Types::IssueType, null: true
 
-    alias_method :project, :object
-
     def resolve(**args)
       # The project could have been loaded in batch by `BatchLoader`.
       # At this point we need the `id` of the project to query for issues, so
       # make sure it's loaded and not `nil` before continuing.
-      project.sync if project.respond_to?(:sync)
+      project = object.respond_to?(:sync) ? object.sync : object
       return Issue.none if project.nil?
 
       # Will need to be be made group & namespace aware with
diff --git a/app/graphql/resolvers/merge_requests_resolver.rb b/app/graphql/resolvers/merge_requests_resolver.rb
index b84e60066e121c58a331e37c5620d6e116e0800f..1740d614b69f43a6243f5a7b3d48e26f0cb064b7 100644
--- a/app/graphql/resolvers/merge_requests_resolver.rb
+++ b/app/graphql/resolvers/merge_requests_resolver.rb
@@ -25,8 +25,10 @@ module Resolvers
 
     # rubocop: disable CodeReuse/ActiveRecord
     def batch_load(iid)
-      BatchLoader.for(iid.to_s).batch(key: project) do |iids, loader, args|
-        args[:key].merge_requests.where(iid: iids).each do |mr|
+      BatchLoader::GraphQL.for(iid.to_s).batch(key: project) do |iids, loader, args|
+        arg_key = args[:key].respond_to?(:sync) ? args[:key].sync : args[:key]
+
+        arg_key.merge_requests.where(iid: iids).each do |mr|
           loader.call(mr.iid.to_s, mr)
         end
       end
diff --git a/app/graphql/resolvers/namespace_projects_resolver.rb b/app/graphql/resolvers/namespace_projects_resolver.rb
index 677ea808aebed4061c661b0490cc353f043543b0..f5b60f91be6b027a45d194f1f14352522780f444 100644
--- a/app/graphql/resolvers/namespace_projects_resolver.rb
+++ b/app/graphql/resolvers/namespace_projects_resolver.rb
@@ -9,13 +9,11 @@ module Resolvers
 
     type Types::ProjectType, null: true
 
-    alias_method :namespace, :object
-
     def resolve(include_subgroups:)
       # The namespace could have been loaded in batch by `BatchLoader`.
       # At this point we need the `id` or the `full_path` of the namespace
       # to query for projects, so make sure it's loaded and not `nil` before continuing.
-      namespace.sync if namespace.respond_to?(:sync)
+      namespace = object.respond_to?(:sync) ? object.sync : object
       return Project.none if namespace.nil?
 
       if include_subgroups
diff --git a/ee/app/graphql/resolvers/design_management/design_resolver.rb b/ee/app/graphql/resolvers/design_management/design_resolver.rb
index a963f6e3312d7d6828a10c5b0ee5394700f96e79..a144c15c8850a88fc3dfef457dcd236fa7dd74dc 100644
--- a/ee/app/graphql/resolvers/design_management/design_resolver.rb
+++ b/ee/app/graphql/resolvers/design_management/design_resolver.rb
@@ -10,7 +10,7 @@ module Resolvers
                             'If argument is omitted or nil then all designs will reflect the latest version.'
 
       def resolve(at_version: nil)
-        version = at_version ? GitlabSchema.object_from_id(at_version) : nil
+        version = at_version ? GitlabSchema.object_from_id(at_version)&.sync : nil
 
         ::DesignManagement::DesignsFinder.new(
           object.issue,
diff --git a/ee/app/graphql/resolvers/design_management/version_resolver.rb b/ee/app/graphql/resolvers/design_management/version_resolver.rb
index 431f6b28a738e3482a1fc69272be5ee1f868db28..c33974103e6f67c7827ad9f46317786e45790af5 100644
--- a/ee/app/graphql/resolvers/design_management/version_resolver.rb
+++ b/ee/app/graphql/resolvers/design_management/version_resolver.rb
@@ -15,7 +15,7 @@ module Resolvers
         # for consistency we should only present versions up to the given
         # version here.
         at_version = Gitlab::Graphql::FindArgumentInParent.find(parent, :at_version, limit_depth: 4)
-        version = at_version ? GitlabSchema.object_from_id(at_version) : nil
+        version = at_version ? GitlabSchema.object_from_id(at_version).sync : nil
 
         ::DesignManagement::VersionsFinder.new(
           design_or_collection,
diff --git a/ee/app/graphql/resolvers/epic_resolver.rb b/ee/app/graphql/resolvers/epic_resolver.rb
index cf5b090b528e17d680810031a45dad21b92cbd5b..6383cba9df6f096ccf41bcd8419df818b56b77ca 100644
--- a/ee/app/graphql/resolvers/epic_resolver.rb
+++ b/ee/app/graphql/resolvers/epic_resolver.rb
@@ -25,7 +25,9 @@ module Resolvers
     type Types::EpicType, null: true
 
     def resolve(**args)
-      return [] unless object.present?
+      @resolver_object = object.respond_to?(:sync) ? object.sync : object
+
+      return [] unless resolver_object.present?
       return [] unless epic_feature_enabled?
 
       validate_date_params!(args)
@@ -35,6 +37,8 @@ module Resolvers
 
     private
 
+    attr_reader :resolver_object
+
     def find_epics(args)
       EpicsFinder.new(context[:current_user], args).execute
     end
@@ -62,17 +66,17 @@ module Resolvers
       transformed
     end
 
-    # `object` refers to the object we're currently querying on, and is usually a `Group`
+    # `resolver_object` refers to the object we're currently querying on, and is usually a `Group`
     # when querying an Epic.  In the case of field that uses this resolver, for example
-    # an Epic's `children` field, then `object` is an `EpicPresenter` (rather than an Epic).
+    # an Epic's `children` field, then `resolver_object` is an `EpicPresenter` (rather than an Epic).
     # But that's the epic we need in order to scope the find to only children of this epic,
     # using the `parent_id`
     def parent
-      object if object.is_a?(EpicPresenter)
+      resolver_object if resolver_object.is_a?(EpicPresenter)
     end
 
     def group
-      return object if object.is_a?(Group)
+      return resolver_object if resolver_object.is_a?(Group)
 
       parent.group
     end
diff --git a/ee/app/graphql/types/design_management/design_type.rb b/ee/app/graphql/types/design_management/design_type.rb
index 067da5351796ae4c0f008d4f9131cc43a2807032..a6430e2cb358d59d27c275dc0830d36ae66d3ca0 100644
--- a/ee/app/graphql/types/design_management/design_type.rb
+++ b/ee/app/graphql/types/design_management/design_type.rb
@@ -35,9 +35,10 @@ module Types
         # If no argument is found then a nil value for sha is fine
         # and the image displayed will be the latest version
         version_id = Gitlab::Graphql::FindArgumentInParent.find(parent, :at_version, limit_depth: 4)
-        sha = version_id ? GitlabSchema.object_from_id(version_id).sha : nil
+        sha = version_id ? GitlabSchema.object_from_id(version_id)&.sync&.sha : nil
 
         project = Gitlab::Graphql::Loaders::BatchModelLoader.new(Project, design.project_id).find
+        project = project&.sync
 
         Gitlab::Routing.url_helpers.project_design_url(project, design, sha)
       end
diff --git a/ee/spec/graphql/resolvers/epic_resolver_spec.rb b/ee/spec/graphql/resolvers/epic_resolver_spec.rb
index 6a8c8b75e423af2fdf12083b6bc434fb469b9b20..b266f539e350910ceb8bc9253c88f4a795dccbae 100644
--- a/ee/spec/graphql/resolvers/epic_resolver_spec.rb
+++ b/ee/spec/graphql/resolvers/epic_resolver_spec.rb
@@ -125,7 +125,7 @@ describe Resolvers::EpicResolver do
 
   context "when passing a non existent, batch loaded group" do
     let(:group) do
-      BatchLoader.for("non-existent-path").batch do |_fake_paths, loader, _|
+      BatchLoader::GraphQL.for("non-existent-path").batch do |_fake_paths, loader, _|
         loader.call("non-existent-path", nil)
       end
     end
diff --git a/lib/gitlab/graphql/authorize/authorize_field_service.rb b/lib/gitlab/graphql/authorize/authorize_field_service.rb
index 3b5dde2fde58ede5926f8c5bb30d4c10fe39a3fb..0b11ea2f6082c02b3449bcc9e29f8e00950d3491 100644
--- a/lib/gitlab/graphql/authorize/authorize_field_service.rb
+++ b/lib/gitlab/graphql/authorize/authorize_field_service.rb
@@ -54,14 +54,14 @@ module Gitlab
             # The field is a built-in/scalar type, or a list of scalars
             # authorize using the parent's object
             parent_typed_object.object
-          elsif resolved_type.respond_to?(:object)
-            # The field is a type representing a single object, we'll authorize
-            # against the object directly
-            resolved_type.object
           elsif @field.connection? || resolved_type.is_a?(Array)
             # The field is a connection or a list of non-built-in types, we'll
             # authorize each element when rendering
             nil
+          elsif resolved_type.respond_to?(:object)
+            # The field is a type representing a single object, we'll authorize
+            # against the object directly
+            resolved_type.object
           else
             # Resolved type is a single object that might not be loaded yet by
             # the batchloader, we'll authorize that
diff --git a/lib/gitlab/graphql/authorize/authorize_resource.rb b/lib/gitlab/graphql/authorize/authorize_resource.rb
index ef5caaf5b0e52fafa00c9aaf27e53d8d1d7552b9..6844367454f02febcbb5e23c5989c6d426c5033a 100644
--- a/lib/gitlab/graphql/authorize/authorize_resource.rb
+++ b/lib/gitlab/graphql/authorize/authorize_resource.rb
@@ -29,19 +29,25 @@ module Gitlab
 
         def authorized_find!(*args)
           object = find_object(*args)
+          object = object.sync if object.respond_to?(:sync)
+
           authorize!(object)
 
           object
         end
 
         def authorize!(object)
-          unless authorized?(object)
+          unless authorized_resource?(object)
             raise Gitlab::Graphql::Errors::ResourceNotAvailable,
                   "The resource that you are attempting to access does not exist or you don't have permission to perform this action"
           end
         end
 
-        def authorized?(object)
+        # this was named `#authorized?`, however it conflicts with the native
+        # graphql gem version
+        # TODO consider adopting the gem's built in authorization system
+        # https://gitlab.com/gitlab-org/gitlab-ee/issues/13984
+        def authorized_resource?(object)
           # Sanity check. We don't want to accidentally allow a developer to authorize
           # without first adding permissions to authorize against
           if self.class.required_permissions.empty?
diff --git a/lib/gitlab/graphql/loaders/batch_lfs_oid_loader.rb b/lib/gitlab/graphql/loaders/batch_lfs_oid_loader.rb
index 8f34e58a7714084b9f7d58ad5eed02cb60c98555..67511c124e405383246e570a20b6a920675d7edc 100644
--- a/lib/gitlab/graphql/loaders/batch_lfs_oid_loader.rb
+++ b/lib/gitlab/graphql/loaders/batch_lfs_oid_loader.rb
@@ -9,7 +9,7 @@ module Gitlab
         end
 
         def find
-          BatchLoader.for(blob_id).batch(key: repository) do |blob_ids, loader, batch_args|
+          BatchLoader::GraphQL.for(blob_id).batch(key: repository) do |blob_ids, loader, batch_args|
             Gitlab::Git::Blob.batch_lfs_pointers(batch_args[:key], blob_ids).each do |loaded_blob|
               loader.call(loaded_blob.id, loaded_blob.lfs_oid)
             end
diff --git a/lib/gitlab/graphql/loaders/batch_model_loader.rb b/lib/gitlab/graphql/loaders/batch_model_loader.rb
index 50d3293fcbb08f99abcad60b916461daa9ba979e..164fe74148c5df97ab26d8d6eab1e5a335b8c91b 100644
--- a/lib/gitlab/graphql/loaders/batch_model_loader.rb
+++ b/lib/gitlab/graphql/loaders/batch_model_loader.rb
@@ -12,7 +12,7 @@ module Gitlab
 
         # rubocop: disable CodeReuse/ActiveRecord
         def find
-          BatchLoader.for({ model: model_class, id: model_id.to_i }).batch do |loader_info, loader|
+          BatchLoader::GraphQL.for({ model: model_class, id: model_id.to_i }).batch do |loader_info, loader|
             per_model = loader_info.group_by { |info| info[:model] }
             per_model.each do |model, info|
               ids = info.map { |i| i[:id] }
diff --git a/lib/gitlab/graphql/loaders/batch_project_statistics_loader.rb b/lib/gitlab/graphql/loaders/batch_project_statistics_loader.rb
index 5e151f4dbd754598d29d04dc24f4c24a8ed793df..449f4160a6cdd751460bd611d05c1055c3b821f7 100644
--- a/lib/gitlab/graphql/loaders/batch_project_statistics_loader.rb
+++ b/lib/gitlab/graphql/loaders/batch_project_statistics_loader.rb
@@ -11,7 +11,7 @@ module Gitlab
         end
 
         def find
-          BatchLoader.for(project_id).batch do |project_ids, loader|
+          BatchLoader::GraphQL.for(project_id).batch do |project_ids, loader|
             ProjectStatistics.for_project_ids(project_ids).each do |statistics|
               loader.call(statistics.project_id, statistics)
             end
diff --git a/lib/gitlab/graphql/loaders/batch_root_storage_statistics_loader.rb b/lib/gitlab/graphql/loaders/batch_root_storage_statistics_loader.rb
index a0312366d664e65ab6586b5cd97de536c8131b0d..366aa74d4353ef15c5f5d591bf172b4d3b05ec0c 100644
--- a/lib/gitlab/graphql/loaders/batch_root_storage_statistics_loader.rb
+++ b/lib/gitlab/graphql/loaders/batch_root_storage_statistics_loader.rb
@@ -11,7 +11,7 @@ module Gitlab
         end
 
         def find
-          BatchLoader.for(namespace_id).batch do |namespace_ids, loader|
+          BatchLoader::GraphQL.for(namespace_id).batch do |namespace_ids, loader|
             Namespace::RootStorageStatistics.for_namespace_ids(namespace_ids).each do |statistics|
               loader.call(statistics.namespace_id, statistics)
             end
diff --git a/lib/gitlab/graphql/loaders/pipeline_for_sha_loader.rb b/lib/gitlab/graphql/loaders/pipeline_for_sha_loader.rb
index 81c5cabf45124235244602aecbeaf5301a8d13ff..70344392138090bcd9d4c672c2a6b43010089f6b 100644
--- a/lib/gitlab/graphql/loaders/pipeline_for_sha_loader.rb
+++ b/lib/gitlab/graphql/loaders/pipeline_for_sha_loader.rb
@@ -11,7 +11,7 @@ module Gitlab
         end
 
         def find_last
-          BatchLoader.for(sha).batch(key: project) do |shas, loader, args|
+          BatchLoader::GraphQL.for(sha).batch(key: project) do |shas, loader, args|
             pipelines = args[:key].ci_pipelines.latest_for_shas(shas)
 
             pipelines.each do |pipeline|
diff --git a/spec/graphql/gitlab_schema_spec.rb b/spec/graphql/gitlab_schema_spec.rb
index dec6b23d72a6ecdb1b2249a5fcfbeb2a2ffb5c49..0a27bbecfef35df5e3663383caefa4576f905751 100644
--- a/spec/graphql/gitlab_schema_spec.rb
+++ b/spec/graphql/gitlab_schema_spec.rb
@@ -129,7 +129,7 @@ describe GitlabSchema do
 
         result = described_class.object_from_id(user.to_global_id.to_s)
 
-        expect(result.__sync).to eq(user)
+        expect(result.sync).to eq(user)
       end
 
       it 'batchloads the queries' do
@@ -138,7 +138,7 @@ describe GitlabSchema do
 
         expect do
           [described_class.object_from_id(user1.to_global_id),
-           described_class.object_from_id(user2.to_global_id)].map(&:__sync)
+           described_class.object_from_id(user2.to_global_id)].map(&:sync)
         end.not_to exceed_query_limit(1)
       end
     end
@@ -149,7 +149,7 @@ describe GitlabSchema do
 
         result = described_class.object_from_id(note.to_global_id)
 
-        expect(result.__sync).to eq(note)
+        expect(result.sync).to eq(note)
       end
 
       it 'batchloads the queries' do
@@ -158,7 +158,7 @@ describe GitlabSchema do
 
         expect do
           [described_class.object_from_id(note1.to_global_id),
-           described_class.object_from_id(note2.to_global_id)].map(&:__sync)
+           described_class.object_from_id(note2.to_global_id)].map(&:sync)
         end.not_to exceed_query_limit(1)
       end
     end
diff --git a/spec/graphql/mutations/concerns/mutations/resolves_project_spec.rb b/spec/graphql/mutations/concerns/mutations/resolves_project_spec.rb
index 19f5a8907a2006ddfbf9eb4c0992b30645c21114..aa0f5c55902b3205d06a05de9ea207f7842ffc4a 100644
--- a/spec/graphql/mutations/concerns/mutations/resolves_project_spec.rb
+++ b/spec/graphql/mutations/concerns/mutations/resolves_project_spec.rb
@@ -14,6 +14,6 @@ describe Mutations::ResolvesProject do
     project = create(:project)
 
     expect(Resolvers::ProjectResolver).to receive(:new).with(object: nil, context: context).and_call_original
-    expect(mutation.resolve_project(full_path: project.full_path)).to eq(project)
+    expect(mutation.resolve_project(full_path: project.full_path).sync).to eq(project)
   end
 end
diff --git a/spec/graphql/resolvers/group_resolver_spec.rb b/spec/graphql/resolvers/group_resolver_spec.rb
index 5eb9cd06d159e493a13231798d34bcf7ae40606b..7dec9ac1aa549a6c093bdb2b2236aaf5fdcb855b 100644
--- a/spec/graphql/resolvers/group_resolver_spec.rb
+++ b/spec/graphql/resolvers/group_resolver_spec.rb
@@ -12,7 +12,7 @@ describe Resolvers::GroupResolver do
     it 'batch-resolves groups by full path' do
       paths = [group1.full_path, group2.full_path]
 
-      result = batch(max_queries: 1) do
+      result = batch_sync(max_queries: 1) do
         paths.map { |path| resolve_group(path) }
       end
 
@@ -20,7 +20,7 @@ describe Resolvers::GroupResolver do
     end
 
     it 'resolves an unknown full_path to nil' do
-      result = batch { resolve_group('unknown/project') }
+      result = batch_sync { resolve_group('unknown/project') }
 
       expect(result).to be_nil
     end
diff --git a/spec/graphql/resolvers/issues_resolver_spec.rb b/spec/graphql/resolvers/issues_resolver_spec.rb
index 798fe00de977b8a00a6e0badc65c790442da6216..d122c081069929467c44397391d4a1becc88fc58 100644
--- a/spec/graphql/resolvers/issues_resolver_spec.rb
+++ b/spec/graphql/resolvers/issues_resolver_spec.rb
@@ -110,7 +110,7 @@ describe Resolvers::IssuesResolver do
 
   context "when passing a non existent, batch loaded project" do
     let(:project) do
-      BatchLoader.for("non-existent-path").batch do |_fake_paths, loader, _|
+      BatchLoader::GraphQL.for("non-existent-path").batch do |_fake_paths, loader, _|
         loader.call("non-existent-path", nil)
       end
     end
diff --git a/spec/graphql/resolvers/merge_requests_resolver_spec.rb b/spec/graphql/resolvers/merge_requests_resolver_spec.rb
index ab3c426b2cd608b9f2bf60472e37fe0507cf6e9c..97b8e5ed41ccb924c51041c674085a97df60d020 100644
--- a/spec/graphql/resolvers/merge_requests_resolver_spec.rb
+++ b/spec/graphql/resolvers/merge_requests_resolver_spec.rb
@@ -17,7 +17,7 @@ describe Resolvers::MergeRequestsResolver do
 
   describe '#resolve' do
     it 'batch-resolves by target project full path and individual IID' do
-      result = batch(max_queries: 2) do
+      result = batch_sync(max_queries: 2) do
         resolve_mr(project, iid: iid_1) + resolve_mr(project, iid: iid_2)
       end
 
@@ -25,7 +25,7 @@ describe Resolvers::MergeRequestsResolver do
     end
 
     it 'batch-resolves by target project full path and IIDS' do
-      result = batch(max_queries: 2) do
+      result = batch_sync(max_queries: 2) do
         resolve_mr(project, iids: [iid_1, iid_2])
       end
 
@@ -33,7 +33,7 @@ describe Resolvers::MergeRequestsResolver do
     end
 
     it 'can batch-resolve merge requests from different projects' do
-      result = batch(max_queries: 3) do
+      result = batch_sync(max_queries: 3) do
         resolve_mr(project, iid: iid_1) +
           resolve_mr(project, iid: iid_2) +
           resolve_mr(other_project, iid: other_iid)
@@ -43,13 +43,13 @@ describe Resolvers::MergeRequestsResolver do
     end
 
     it 'resolves an unknown iid to be empty' do
-      result = batch { resolve_mr(project, iid: -1) }
+      result = batch_sync { resolve_mr(project, iid: -1) }
 
-      expect(result).to be_empty
+      expect(result.compact).to be_empty
     end
 
     it 'resolves empty iids to be empty' do
-      result = batch { resolve_mr(project, iids: []) }
+      result = batch_sync { resolve_mr(project, iids: []) }
 
       expect(result).to be_empty
     end
diff --git a/spec/graphql/resolvers/namespace_projects_resolver_spec.rb b/spec/graphql/resolvers/namespace_projects_resolver_spec.rb
index 47591445fc0f252ef9b241f8cb042adf65bd4a07..639cc69650b74b657e3e71bde91136067477cb02 100644
--- a/spec/graphql/resolvers/namespace_projects_resolver_spec.rb
+++ b/spec/graphql/resolvers/namespace_projects_resolver_spec.rb
@@ -46,7 +46,7 @@ describe Resolvers::NamespaceProjectsResolver do
 
   context "when passing a non existent, batch loaded namespace" do
     let(:namespace) do
-      BatchLoader.for("non-existent-path").batch do |_fake_paths, loader, _|
+      BatchLoader::GraphQL.for("non-existent-path").batch do |_fake_paths, loader, _|
         loader.call("non-existent-path", nil)
       end
     end
diff --git a/spec/graphql/resolvers/project_resolver_spec.rb b/spec/graphql/resolvers/project_resolver_spec.rb
index 4fdbb3aa43e8469bb958c40b177cea56ccbb3191..d0fc295790913873b8e747b4333162622512ab76 100644
--- a/spec/graphql/resolvers/project_resolver_spec.rb
+++ b/spec/graphql/resolvers/project_resolver_spec.rb
@@ -12,7 +12,7 @@ describe Resolvers::ProjectResolver do
     it 'batch-resolves projects by full path' do
       paths = [project1.full_path, project2.full_path]
 
-      result = batch(max_queries: 1) do
+      result = batch_sync(max_queries: 1) do
         paths.map { |path| resolve_project(path) }
       end
 
@@ -20,7 +20,7 @@ describe Resolvers::ProjectResolver do
     end
 
     it 'resolves an unknown full_path to nil' do
-      result = batch { resolve_project('unknown/project') }
+      result = batch_sync { resolve_project('unknown/project') }
 
       expect(result).to be_nil
     end
diff --git a/spec/lib/gitlab/graphql/authorize/authorize_resource_spec.rb b/spec/lib/gitlab/graphql/authorize/authorize_resource_spec.rb
index 50138d272c4a2264666e5a75bf7f839e2b749de0..23762666ba8d0cb8a3a4a2def38e154a0aaba082 100644
--- a/spec/lib/gitlab/graphql/authorize/authorize_resource_spec.rb
+++ b/spec/lib/gitlab/graphql/authorize/authorize_resource_spec.rb
@@ -46,9 +46,9 @@ describe Gitlab::Graphql::Authorize::AuthorizeResource do
       end
     end
 
-    describe '#authorized?' do
+    describe '#authorized_resource?' do
       it 'is true' do
-        expect(loading_resource.authorized?(project)).to be(true)
+        expect(loading_resource.authorized_resource?(project)).to be(true)
       end
     end
   end
@@ -72,9 +72,9 @@ describe Gitlab::Graphql::Authorize::AuthorizeResource do
       end
     end
 
-    describe '#authorized?' do
+    describe '#authorized_resource?' do
       it 'is false' do
-        expect(loading_resource.authorized?(project)).to be(false)
+        expect(loading_resource.authorized_resource?(project)).to be(false)
       end
     end
   end
@@ -121,9 +121,9 @@ describe Gitlab::Graphql::Authorize::AuthorizeResource do
       end
     end
 
-    describe '#authorized?' do
+    describe '#authorized_resource?' do
       it 'raises a comprehensive error message' do
-        expect { loading_resource.authorized?(project) }.to raise_error(error)
+        expect { loading_resource.authorized_resource?(project) }.to raise_error(error)
       end
     end
   end
diff --git a/spec/lib/gitlab/graphql/loaders/batch_lfs_oid_loader_spec.rb b/spec/lib/gitlab/graphql/loaders/batch_lfs_oid_loader_spec.rb
index 46dd1777285314bc0f00681b4b076a84d2f7f37c..22d8aa4274a7e6ab4ca5cd93bff16ad76be94e95 100644
--- a/spec/lib/gitlab/graphql/loaders/batch_lfs_oid_loader_spec.rb
+++ b/spec/lib/gitlab/graphql/loaders/batch_lfs_oid_loader_spec.rb
@@ -12,7 +12,7 @@ describe Gitlab::Graphql::Loaders::BatchLfsOidLoader do
     it 'batch-resolves LFS blob IDs' do
       expect(Gitlab::Git::Blob).to receive(:batch_lfs_pointers).once.and_call_original
 
-      result = batch do
+      result = batch_sync do
         [blob, otherblob].map { |b| described_class.new(repository, b.id).find }
       end
 
diff --git a/spec/lib/gitlab/graphql/loaders/batch_model_loader_spec.rb b/spec/lib/gitlab/graphql/loaders/batch_model_loader_spec.rb
index 4609593ef6adede66cc1f802d760a126cb2d4db9..a4bbd868558adfa140d2e821d0d501b87fb27c58 100644
--- a/spec/lib/gitlab/graphql/loaders/batch_model_loader_spec.rb
+++ b/spec/lib/gitlab/graphql/loaders/batch_model_loader_spec.rb
@@ -9,8 +9,8 @@ describe Gitlab::Graphql::Loaders::BatchModelLoader do
       issue_result = described_class.new(Issue, issue.id).find
       user_result = described_class.new(User, user.id).find
 
-      expect(issue_result.__sync).to eq(issue)
-      expect(user_result.__sync).to eq(user)
+      expect(issue_result.sync).to eq(issue)
+      expect(user_result.sync).to eq(user)
     end
 
     it 'only queries once per model' do
@@ -21,7 +21,7 @@ describe Gitlab::Graphql::Loaders::BatchModelLoader do
       expect do
         [described_class.new(User, other_user.id).find,
          described_class.new(User, user.id).find,
-         described_class.new(Issue, issue.id).find].map(&:__sync)
+         described_class.new(Issue, issue.id).find].map(&:sync)
       end.not_to exceed_query_limit(2)
     end
   end
diff --git a/spec/lib/gitlab/graphql/loaders/pipeline_for_sha_loader_spec.rb b/spec/lib/gitlab/graphql/loaders/pipeline_for_sha_loader_spec.rb
index 927476cc65500e5a5f9ce5b5139df038293f4388..136027736c3fadcdd38f4c42915470abc60ea191 100644
--- a/spec/lib/gitlab/graphql/loaders/pipeline_for_sha_loader_spec.rb
+++ b/spec/lib/gitlab/graphql/loaders/pipeline_for_sha_loader_spec.rb
@@ -10,7 +10,7 @@ describe Gitlab::Graphql::Loaders::PipelineForShaLoader do
       pipeline2 = create(:ci_pipeline, project: project, ref: project.default_branch, sha: project.commit.sha)
       pipeline3 = create(:ci_pipeline, project: project, ref: 'improve/awesome', sha: project.commit('improve/awesome').sha)
 
-      result = batch(max_queries: 1) do
+      result = batch_sync(max_queries: 1) do
         [pipeline1.sha, pipeline3.sha].map { |sha| described_class.new(project, sha).find_last }
       end
 
diff --git a/spec/requests/api/graphql/mutations/merge_requests/set_wip_spec.rb b/spec/requests/api/graphql/mutations/merge_requests/set_wip_spec.rb
index d75f0df9fd35bdea9beb348c693895a6354e6cb8..3a8a2bae939b61a5c262fdc44e3e2fa1362b198c 100644
--- a/spec/requests/api/graphql/mutations/merge_requests/set_wip_spec.rb
+++ b/spec/requests/api/graphql/mutations/merge_requests/set_wip_spec.rb
@@ -13,7 +13,7 @@ describe 'Setting WIP status of a merge request' do
       project_path: project.full_path,
       iid: merge_request.iid.to_s
     }
-    graphql_mutation(:merge_request_set_wip, variables.merge(input))
+    graphql_mutation(:merge_request_set_wip, variables.merge(input), "clientMutationId\nerrors\nmergeRequest { id\ntitle }")
   end
 
   def mutation_response
diff --git a/spec/support/helpers/graphql_helpers.rb b/spec/support/helpers/graphql_helpers.rb
index d86371d70b972cc18d075728db8cd7d0a79e4df5..beb346b2855bf38cf45306ad4e2f4e8aa5309a69 100644
--- a/spec/support/helpers/graphql_helpers.rb
+++ b/spec/support/helpers/graphql_helpers.rb
@@ -34,6 +34,14 @@ module GraphqlHelpers
     end
   end
 
+  # BatchLoader::GraphQL returns a wrapper, so we need to :sync in order
+  # to get the actual values
+  def batch_sync(max_queries: nil, &blk)
+    result = batch(max_queries: nil, &blk)
+
+    result.is_a?(Array) ? result.map(&:sync) : result&.sync
+  end
+
   def graphql_query_for(name, attributes = {}, fields = nil)
     <<~QUERY
     {
@@ -114,7 +122,11 @@ module GraphqlHelpers
     FIELDS
   end
 
-  def all_graphql_fields_for(class_name, parent_types = Set.new)
+  def all_graphql_fields_for(class_name, parent_types = Set.new, max_depth: 3)
+    # pulling _all_ fields can generate a _huge_ query (like complexity 180,000),
+    # and significantly increase spec runtime. so limit the depth by default
+    return if max_depth <= 0
+
     allow_unlimited_graphql_complexity
     allow_unlimited_graphql_depth
 
@@ -133,9 +145,9 @@ module GraphqlHelpers
 
       if nested_fields?(field)
         fields =
-          all_graphql_fields_for(singular_field_type, parent_types | [type])
+          all_graphql_fields_for(singular_field_type, parent_types | [type], max_depth: max_depth - 1)
 
-        "#{name} { #{fields} }"
+        "#{name} { #{fields} }" unless fields.blank?
       else
         name
       end
diff --git a/spec/support/shared_examples/graphql/notes_on_noteables_shared_examples.rb b/spec/support/shared_examples/graphql/notes_on_noteables_shared_examples.rb
index 323d1c51ffde47d997d792b2457acb9d0209d53a..9a60825855f16b5b44197a471891bb8e35055b93 100644
--- a/spec/support/shared_examples/graphql/notes_on_noteables_shared_examples.rb
+++ b/spec/support/shared_examples/graphql/notes_on_noteables_shared_examples.rb
@@ -46,7 +46,7 @@ shared_context 'exposing regular notes on a noteable in GraphQL' do
       discussions {
         edges {
           node {
-            #{all_graphql_fields_for('Discussion')}
+            #{all_graphql_fields_for('Discussion', max_depth: 4)}
           }
         }
       }