diff --git a/app/serializers/deployment_entity.rb b/app/serializers/deployment_entity.rb
index 2bafcee0109f7c49f72ecac2cc19b5b12e028898..943c707218d0b3c48836f0341ef2a40ab48e1a7b 100644
--- a/app/serializers/deployment_entity.rb
+++ b/app/serializers/deployment_entity.rb
@@ -22,8 +22,18 @@ class DeploymentEntity < Grape::Entity
   expose :last?
   expose :user, using: UserEntity
 
+  expose :deployable do |deployment, opts|
+    deployment.deployable.yield_self do |deployable|
+      if include_details?
+        JobEntity.represent(deployable, opts)
+      elsif can_read_deployables?
+        { name: deployable.name,
+          build_path: project_job_path(deployable.project, deployable) }
+      end
+    end
+  end
+
   expose :commit, using: CommitEntity, if: -> (*) { include_details? }
-  expose :deployable, using: JobEntity, if: -> (*) { include_details? }
   expose :manual_actions, using: JobEntity, if: -> (*) { include_details? && can_create_deployment? }
   expose :scheduled_actions, using: JobEntity, if: -> (*) { include_details? && can_create_deployment? }
 
@@ -36,4 +46,13 @@ class DeploymentEntity < Grape::Entity
   def can_create_deployment?
     can?(request.current_user, :create_deployment, request.project)
   end
+
+  def can_read_deployables?
+    ##
+    # We intentionally do not check `:read_build, deployment.deployable`
+    # because it triggers a policy evaluation that involves multiple
+    # Gitaly calls that might not be cached.
+    #
+    can?(request.current_user, :read_build, request.project)
+  end
 end
diff --git a/spec/fixtures/api/schemas/environment.json b/spec/fixtures/api/schemas/environment.json
index 9a10ab18c30306fb5767996b840536265baf1949..5b1e3c049fa6a1d26bdcad734f95507c63d88b9b 100644
--- a/spec/fixtures/api/schemas/environment.json
+++ b/spec/fixtures/api/schemas/environment.json
@@ -31,7 +31,11 @@
     "last_deployment": {
       "oneOf": [
         { "type": "null" },
-        { "$ref": "deployment.json" }
+        { "$ref": "deployment.json" },
+        {
+          "name": { "type": "string" },
+          "build_path": { "type": "string" }
+        }
       ]
     }
   },
diff --git a/spec/serializers/build_details_entity_spec.rb b/spec/serializers/build_details_entity_spec.rb
index 68cf428ed38da700436e81045008a8d51183eff6..9c2e5c79a9dee82d492586d7005cd78ec87f10ef 100644
--- a/spec/serializers/build_details_entity_spec.rb
+++ b/spec/serializers/build_details_entity_spec.rb
@@ -142,7 +142,7 @@ describe BuildDetailsEntity do
         response = subject.with_indifferent_access
 
         response.dig(:deployment_status, :environment, :last_deployment).tap do |deployment|
-          expect(deployment).not_to include(:commit, :deployable, :manual_actions, :scheduled_actions)
+          expect(deployment).not_to include(:commit, :manual_actions, :scheduled_actions)
         end
       end
     end
diff --git a/spec/serializers/deployment_entity_spec.rb b/spec/serializers/deployment_entity_spec.rb
index f0bbf90c6c67e494ba3046b2802d11b327f0172e..37614cc0b4ca8d03389c266f7bcfc887d4721708 100644
--- a/spec/serializers/deployment_entity_spec.rb
+++ b/spec/serializers/deployment_entity_spec.rb
@@ -93,13 +93,22 @@ describe DeploymentEntity do
   end
 
   context 'when deployment details serialization was disabled' do
+    include Gitlab::Routing
+
     let(:entity) do
       described_class.new(deployment, request: request, deployment_details: false)
     end
 
     it 'does not serialize deployment details' do
       expect(subject.with_indifferent_access)
-        .not_to include(:commit, :deployable, :manual_actions, :scheduled_actions)
+        .not_to include(:commit, :manual_actions, :scheduled_actions)
+    end
+
+    it 'only exposes deployable name and path' do
+      project_job_path(project, deployment.deployable).tap do |path|
+        expect(subject.fetch(:deployable))
+          .to eq('name' => 'test', 'build_path' => path)
+      end
     end
   end
 end