diff --git a/e2e/src/api/specs/stack.e2e-spec.ts b/e2e/src/api/specs/stack.e2e-spec.ts
index bf34369ee3..36b600bec9 100644
--- a/e2e/src/api/specs/stack.e2e-spec.ts
+++ b/e2e/src/api/specs/stack.e2e-spec.ts
@@ -119,93 +119,57 @@ describe('/stacks', () => {
       const stacksAfter = await searchStacks({}, { headers: asBearerAuth(user1.accessToken) });
       expect(stacksAfter.length).toBe(stacksBefore.length);
     });
-
-    // it('should require a valid parent id', async () => {
-    //   const { status, body } = await request(app)
-    //     .put('/assets')
-    //     .set('Authorization', `Bearer ${user1.accessToken}`)
-    //     .send({ stackParentId: uuidDto.invalid, ids: [stackAssets[0].id] });
-
-    //   expect(status).toBe(400);
-    //   expect(body).toEqual(errorDto.badRequest(['stackParentId must be a UUID']));
-    // });
   });
 
-  // it('should require access to the parent', async () => {
-  //   const { status, body } = await request(app)
-  //     .put('/assets')
-  //     .set('Authorization', `Bearer ${user1.accessToken}`)
-  //     .send({ stackParentId: stackAssets[3].id, ids: [user1Assets[0].id] });
+  describe('GET /assets/:id', () => {
+    it('should include stack details for the primary asset', async () => {
+      const [asset1, asset2] = await Promise.all([
+        utils.createAsset(user1.accessToken),
+        utils.createAsset(user1.accessToken),
+      ]);
 
-  //   expect(status).toBe(400);
-  //   expect(body).toEqual(errorDto.noPermission);
-  // });
+      await utils.createStack(user1.accessToken, [asset1.id, asset2.id]);
 
-  // it('should add stack children', async () => {
-  //   const { status } = await request(app)
-  //     .put('/assets')
-  //     .set('Authorization', `Bearer ${stackUser.accessToken}`)
-  //     .send({ stackParentId: stackAssets[0].id, ids: [stackAssets[3].id] });
+      const { status, body } = await request(app)
+        .get(`/assets/${asset1.id}`)
+        .set('Authorization', `Bearer ${user1.accessToken}`);
 
-  //   expect(status).toBe(204);
+      expect(status).toBe(200);
+      expect(body).toEqual(
+        expect.objectContaining({
+          id: asset1.id,
+          stack: {
+            id: expect.any(String),
+            assetCount: 2,
+            primaryAssetId: asset1.id,
+          },
+        }),
+      );
+    });
 
-  //   const asset = await getAssetInfo({ id: stackAssets[0].id }, { headers: asBearerAuth(stackUser.accessToken) });
-  //   expect(asset.stack).not.toBeUndefined();
-  //   expect(asset.stack).toEqual(expect.arrayContaining([expect.objectContaining({ id: stackAssets[3].id })]));
-  // });
+    it('should include stack details for a non-primary asset', async () => {
+      const [asset1, asset2] = await Promise.all([
+        utils.createAsset(user1.accessToken),
+        utils.createAsset(user1.accessToken),
+      ]);
 
-  // it('should remove stack children', async () => {
-  //   const { status } = await request(app)
-  //     .put('/assets')
-  //     .set('Authorization', `Bearer ${stackUser.accessToken}`)
-  //     .send({ removeParent: true, ids: [stackAssets[1].id] });
+      await utils.createStack(user1.accessToken, [asset1.id, asset2.id]);
 
-  //   expect(status).toBe(204);
+      const { status, body } = await request(app)
+        .get(`/assets/${asset2.id}`)
+        .set('Authorization', `Bearer ${user1.accessToken}`);
 
-  //   const asset = await getAssetInfo({ id: stackAssets[0].id }, { headers: asBearerAuth(stackUser.accessToken) });
-  //   expect(asset.stack).not.toBeUndefined();
-  //   expect(asset.stack).toEqual(
-  //     expect.arrayContaining([
-  //       expect.objectContaining({ id: stackAssets[2].id }),
-  //       expect.objectContaining({ id: stackAssets[3].id }),
-  //     ]),
-  //   );
-  // });
-
-  // it('should remove all stack children', async () => {
-  //   const { status } = await request(app)
-  //     .put('/assets')
-  //     .set('Authorization', `Bearer ${stackUser.accessToken}`)
-  //     .send({ removeParent: true, ids: [stackAssets[2].id, stackAssets[3].id] });
-
-  //   expect(status).toBe(204);
-
-  //   const asset = await getAssetInfo({ id: stackAssets[0].id }, { headers: asBearerAuth(stackUser.accessToken) });
-  //   expect(asset.stack).toBeUndefined();
-  // });
-
-  // it('should merge stack children', async () => {
-  //   // create stack after previous test removed stack children
-  //   await updateAssets(
-  //     { assetBulkUpdateDto: { stackParentId: stackAssets[0].id, ids: [stackAssets[1].id, stackAssets[2].id] } },
-  //     { headers: asBearerAuth(stackUser.accessToken) },
-  //   );
-
-  //   const { status } = await request(app)
-  //     .put('/assets')
-  //     .set('Authorization', `Bearer ${stackUser.accessToken}`)
-  //     .send({ stackParentId: stackAssets[3].id, ids: [stackAssets[0].id] });
-
-  //   expect(status).toBe(204);
-
-  //   const asset = await getAssetInfo({ id: stackAssets[3].id }, { headers: asBearerAuth(stackUser.accessToken) });
-  //   expect(asset.stack).not.toBeUndefined();
-  //   expect(asset.stack).toEqual(
-  //     expect.arrayContaining([
-  //       expect.objectContaining({ id: stackAssets[0].id }),
-  //       expect.objectContaining({ id: stackAssets[1].id }),
-  //       expect.objectContaining({ id: stackAssets[2].id }),
-  //     ]),
-  //   );
-  // });
+      expect(status).toBe(200);
+      expect(body).toEqual(
+        expect.objectContaining({
+          id: asset2.id,
+          stack: {
+            id: expect.any(String),
+            assetCount: 2,
+            primaryAssetId: asset1.id,
+          },
+        }),
+      );
+    });
+  });
 });
diff --git a/server/src/repositories/asset.repository.ts b/server/src/repositories/asset.repository.ts
index ef581d4766..ed1ef73a08 100644
--- a/server/src/repositories/asset.repository.ts
+++ b/server/src/repositories/asset.repository.ts
@@ -284,7 +284,23 @@ export class AssetRepository implements IAssetRepository {
       .$if(!!library, (qb) => qb.select(withLibrary))
       .$if(!!owner, (qb) => qb.select(withOwner))
       .$if(!!smartSearch, withSmartSearch)
-      .$if(!!stack, (qb) => withStack(qb, { assets: !!stack!.assets, count: false }))
+      .$if(!!stack, (qb) =>
+        qb
+          .leftJoin('asset_stack', 'asset_stack.id', 'assets.stackId')
+          .leftJoinLateral(
+            (eb) =>
+              eb
+                .selectFrom('assets as stacked')
+                .selectAll('asset_stack')
+                .select((eb) => eb.fn('array_agg', [eb.table('stacked')]).as('assets'))
+                .where('stacked.deletedAt', 'is', null)
+                .whereRef('stacked.id', '!=', 'asset_stack.primaryAssetId')
+                .whereRef('stacked.stackId', '=', 'asset_stack.id')
+                .as('stacked_assets'),
+            (join) => join.on('asset_stack.id', 'is not', null),
+          )
+          .select((eb) => eb.fn.toJson(eb.table('stacked_assets')).as('stack')),
+      )
       .$if(!!files, (qb) => qb.select(withFiles))
       .$if(!!tags, (qb) => qb.select(withTags))
       .limit(1)