diff --git a/open-api/immich-openapi-specs.json b/open-api/immich-openapi-specs.json
index c4c9e7d193..7a2f191d05 100644
--- a/open-api/immich-openapi-specs.json
+++ b/open-api/immich-openapi-specs.json
@@ -12215,6 +12215,67 @@
         ],
         "type": "object"
       },
+      "SyncAlbumDeleteV1": {
+        "properties": {
+          "albumId": {
+            "type": "string"
+          }
+        },
+        "required": [
+          "albumId"
+        ],
+        "type": "object"
+      },
+      "SyncAlbumV1": {
+        "properties": {
+          "createdAt": {
+            "format": "date-time",
+            "type": "string"
+          },
+          "description": {
+            "type": "string"
+          },
+          "id": {
+            "type": "string"
+          },
+          "isActivityEnabled": {
+            "type": "boolean"
+          },
+          "name": {
+            "type": "string"
+          },
+          "order": {
+            "allOf": [
+              {
+                "$ref": "#/components/schemas/AssetOrder"
+              }
+            ]
+          },
+          "ownerId": {
+            "type": "string"
+          },
+          "thumbnailAssetId": {
+            "nullable": true,
+            "type": "string"
+          },
+          "updatedAt": {
+            "format": "date-time",
+            "type": "string"
+          }
+        },
+        "required": [
+          "createdAt",
+          "description",
+          "id",
+          "isActivityEnabled",
+          "name",
+          "order",
+          "ownerId",
+          "thumbnailAssetId",
+          "updatedAt"
+        ],
+        "type": "object"
+      },
       "SyncAssetDeleteV1": {
         "properties": {
           "assetId": {
@@ -12441,7 +12502,9 @@
           "AssetExifV1",
           "PartnerAssetV1",
           "PartnerAssetDeleteV1",
-          "PartnerAssetExifV1"
+          "PartnerAssetExifV1",
+          "AlbumV1",
+          "AlbumDeleteV1"
         ],
         "type": "string"
       },
@@ -12486,7 +12549,8 @@
           "AssetsV1",
           "AssetExifsV1",
           "PartnerAssetsV1",
-          "PartnerAssetExifsV1"
+          "PartnerAssetExifsV1",
+          "AlbumsV1"
         ],
         "type": "string"
       },
diff --git a/server/src/db.d.ts b/server/src/db.d.ts
index 1b039f9982..f0cb6ba807 100644
--- a/server/src/db.d.ts
+++ b/server/src/db.d.ts
@@ -74,6 +74,13 @@ export interface Albums {
   updateId: Generated<string>;
 }
 
+export interface AlbumsAudit {
+  deletedAt: Generated<Timestamp>;
+  id: Generated<string>;
+  albumId: string;
+  ownerId: string;
+}
+
 export interface AlbumsAssetsAssets {
   albumsId: string;
   assetsId: string;
@@ -463,6 +470,7 @@ export interface VersionHistory {
 export interface DB {
   activity: Activity;
   albums: Albums;
+  albums_audit: AlbumsAudit;
   albums_assets_assets: AlbumsAssetsAssets;
   albums_shared_users_users: AlbumsSharedUsersUsers;
   api_keys: ApiKeys;
diff --git a/server/src/dtos/sync.dto.ts b/server/src/dtos/sync.dto.ts
index cc11c3410b..ed20a3a1a9 100644
--- a/server/src/dtos/sync.dto.ts
+++ b/server/src/dtos/sync.dto.ts
@@ -1,7 +1,7 @@
 import { ApiProperty } from '@nestjs/swagger';
 import { IsEnum, IsInt, IsPositive, IsString } from 'class-validator';
 import { AssetResponseDto } from 'src/dtos/asset-response.dto';
-import { AssetType, AssetVisibility, SyncEntityType, SyncRequestType } from 'src/enum';
+import { AssetOrder, AssetType, AssetVisibility, SyncEntityType, SyncRequestType } from 'src/enum';
 import { Optional, ValidateDate, ValidateUUID } from 'src/validation';
 
 export class AssetFullSyncDto {
@@ -112,6 +112,23 @@ export class SyncAssetExifV1 {
   fps!: number | null;
 }
 
+export class SyncAlbumDeleteV1 {
+  albumId!: string;
+}
+
+export class SyncAlbumV1 {
+  id!: string;
+  ownerId!: string;
+  name!: string;
+  description!: string;
+  createdAt!: Date;
+  updatedAt!: Date;
+  thumbnailAssetId!: string | null;
+  isActivityEnabled!: boolean;
+  @ApiProperty({ enumName: 'AssetOrder', enum: AssetOrder })
+  order!: AssetOrder;
+}
+
 export type SyncItem = {
   [SyncEntityType.UserV1]: SyncUserV1;
   [SyncEntityType.UserDeleteV1]: SyncUserDeleteV1;
@@ -123,10 +140,11 @@ export type SyncItem = {
   [SyncEntityType.PartnerAssetV1]: SyncAssetV1;
   [SyncEntityType.PartnerAssetDeleteV1]: SyncAssetDeleteV1;
   [SyncEntityType.PartnerAssetExifV1]: SyncAssetExifV1;
+  [SyncEntityType.AlbumV1]: SyncAlbumV1;
+  [SyncEntityType.AlbumDeleteV1]: SyncAlbumDeleteV1;
 };
 
 const responseDtos = [
-  //
   SyncUserV1,
   SyncUserDeleteV1,
   SyncPartnerV1,
@@ -134,6 +152,8 @@ const responseDtos = [
   SyncAssetV1,
   SyncAssetDeleteV1,
   SyncAssetExifV1,
+  SyncAlbumV1,
+  SyncAlbumDeleteV1,
 ];
 
 export const extraSyncModels = responseDtos;
diff --git a/server/src/enum.ts b/server/src/enum.ts
index f214593975..b57c279c90 100644
--- a/server/src/enum.ts
+++ b/server/src/enum.ts
@@ -574,6 +574,7 @@ export enum SyncRequestType {
   AssetExifsV1 = 'AssetExifsV1',
   PartnerAssetsV1 = 'PartnerAssetsV1',
   PartnerAssetExifsV1 = 'PartnerAssetExifsV1',
+  AlbumsV1 = 'AlbumsV1',
 }
 
 export enum SyncEntityType {
@@ -590,6 +591,9 @@ export enum SyncEntityType {
   PartnerAssetV1 = 'PartnerAssetV1',
   PartnerAssetDeleteV1 = 'PartnerAssetDeleteV1',
   PartnerAssetExifV1 = 'PartnerAssetExifV1',
+
+  AlbumV1 = 'AlbumV1',
+  AlbumDeleteV1 = 'AlbumDeleteV1',
 }
 
 export enum NotificationLevel {
diff --git a/server/src/repositories/sync.repository.ts b/server/src/repositories/sync.repository.ts
index f0c535ecf2..a697f9bfd3 100644
--- a/server/src/repositories/sync.repository.ts
+++ b/server/src/repositories/sync.repository.ts
@@ -7,8 +7,8 @@ import { DummyValue, GenerateSql } from 'src/decorators';
 import { SyncEntityType } from 'src/enum';
 import { SyncAck } from 'src/types';
 
-type auditTables = 'users_audit' | 'partners_audit' | 'assets_audit';
-type upsertTables = 'users' | 'partners' | 'assets' | 'exif';
+type AuditTables = 'users_audit' | 'partners_audit' | 'assets_audit' | 'albums_audit';
+type UpsertTables = 'users' | 'partners' | 'assets' | 'exif' | 'albums';
 
 @Injectable()
 export class SyncRepository {
@@ -154,19 +154,52 @@ export class SyncRepository {
       .stream();
   }
 
-  private auditTableFilters<T extends keyof Pick<DB, auditTables>, D>(qb: SelectQueryBuilder<DB, T, D>, ack?: SyncAck) {
-    const builder = qb as SelectQueryBuilder<DB, auditTables, D>;
+  @GenerateSql({ params: [DummyValue.UUID], stream: true })
+  getAlbumDeletes(userId: string, ack?: SyncAck) {
+    return this.db
+      .selectFrom('albums_audit')
+      .select(['id', 'albumId'])
+      .where('ownerId', '=', userId)
+      .$if(!!ack, (qb) => qb.where('id', '>', ack!.updateId))
+      .$call((qb) => this.auditTableFilters(qb, ack))
+      .stream();
+  }
+
+  @GenerateSql({ params: [DummyValue.UUID], stream: true })
+  getAlbumUpserts(userId: string, ack?: SyncAck) {
+    return this.db
+      .selectFrom('albums')
+      .$call((qb) => this.upsertTableFilters(qb, ack))
+      .leftJoin('albums_shared_users_users as album_users', 'albums.id', 'album_users.albumsId')
+      .where((eb) => eb.or([eb('albums.ownerId', '=', userId), eb('album_users.usersId', '=', userId)]))
+      .select([
+        'albums.id',
+        'albums.ownerId',
+        'albums.albumName as name',
+        'albums.description',
+        'albums.createdAt',
+        'albums.updatedAt',
+        'albums.albumThumbnailAssetId as thumbnailAssetId',
+        'albums.isActivityEnabled',
+        'albums.order',
+        'albums.updateId',
+      ])
+      .stream();
+  }
+
+  private auditTableFilters<T extends keyof Pick<DB, AuditTables>, D>(qb: SelectQueryBuilder<DB, T, D>, ack?: SyncAck) {
+    const builder = qb as SelectQueryBuilder<DB, AuditTables, D>;
     return builder
       .where('deletedAt', '<', sql.raw<Date>("now() - interval '1 millisecond'"))
       .$if(!!ack, (qb) => qb.where('id', '>', ack!.updateId))
       .orderBy('id', 'asc') as SelectQueryBuilder<DB, T, D>;
   }
 
-  private upsertTableFilters<T extends keyof Pick<DB, upsertTables>, D>(
+  private upsertTableFilters<T extends keyof Pick<DB, UpsertTables>, D>(
     qb: SelectQueryBuilder<DB, T, D>,
     ack?: SyncAck,
   ) {
-    const builder = qb as SelectQueryBuilder<DB, upsertTables, D>;
+    const builder = qb as SelectQueryBuilder<DB, UpsertTables, D>;
     return builder
       .where('updatedAt', '<', sql.raw<Date>("now() - interval '1 millisecond'"))
       .$if(!!ack, (qb) => qb.where('updateId', '>', ack!.updateId))
diff --git a/server/src/schema/functions.ts b/server/src/schema/functions.ts
index 65ad2b72dc..3c04694312 100644
--- a/server/src/schema/functions.ts
+++ b/server/src/schema/functions.ts
@@ -23,6 +23,19 @@ export const immich_uuid_v7 = registerFunction({
   synchronize: false,
 });
 
+export const album_after_insert = registerFunction({
+  name: 'album_after_insert',
+  returnType: 'TRIGGER',
+  language: 'PLPGSQL',
+  body: `
+    BEGIN
+      INSERT INTO users_audit ("userId")
+      SELECT "id"
+      FROM OLD;
+      RETURN NULL;
+    END`,
+});
+
 export const updated_at = registerFunction({
   name: 'updated_at',
   returnType: 'TRIGGER',
diff --git a/server/src/schema/index.ts b/server/src/schema/index.ts
index 1800f08c13..f322dd5c5f 100644
--- a/server/src/schema/index.ts
+++ b/server/src/schema/index.ts
@@ -1,6 +1,7 @@
 import { AssetVisibility } from 'src/enum';
 import { asset_face_source_type, assets_status_enum } from 'src/schema/enums';
 import {
+  album_after_insert,
   assets_delete_audit,
   f_concat_ws,
   f_unaccent,
@@ -46,7 +47,7 @@ import { UserAuditTable } from 'src/schema/tables/user-audit.table';
 import { UserMetadataTable } from 'src/schema/tables/user-metadata.table';
 import { UserTable } from 'src/schema/tables/user.table';
 import { VersionHistoryTable } from 'src/schema/tables/version-history.table';
-import { ConfigurationParameter, Database, Extensions, registerEnum } from 'src/sql-tools';
+import { Database, Extensions, registerEnum } from 'src/sql-tools';
 
 export const asset_visibility_enum = registerEnum({
   name: 'asset_visibility_enum',
@@ -54,7 +55,6 @@ export const asset_visibility_enum = registerEnum({
 });
 
 @Extensions(['uuid-ossp', 'unaccent', 'cube', 'earthdistance', 'pg_trgm', 'plpgsql'])
-@ConfigurationParameter({ name: 'search_path', value: () => '"$user", public, vectors', scope: 'database' })
 @Database({ name: 'immich' })
 export class ImmichDatabase {
   tables = [
@@ -105,6 +105,7 @@ export class ImmichDatabase {
     users_delete_audit,
     partners_delete_audit,
     assets_delete_audit,
+    album_after_insert,
   ];
 
   enum = [assets_status_enum, asset_face_source_type];
diff --git a/server/src/schema/tables/album-audit.table.ts b/server/src/schema/tables/album-audit.table.ts
new file mode 100644
index 0000000000..cf6d944a10
--- /dev/null
+++ b/server/src/schema/tables/album-audit.table.ts
@@ -0,0 +1,17 @@
+import { PrimaryGeneratedUuidV7Column } from 'src/decorators';
+import { Column, CreateDateColumn, Table } from 'src/sql-tools';
+
+@Table('albums_audit')
+export class AlbumAuditTable {
+  @PrimaryGeneratedUuidV7Column()
+  id!: string;
+
+  @Column({ type: 'uuid', indexName: 'IDX_albums_audit_album_id' })
+  albumId!: string;
+
+  @Column({ type: 'uuid', indexName: 'IDX_albums_audit_owner_id' })
+  ownerId!: string;
+
+  @CreateDateColumn({ default: () => 'clock_timestamp()', indexName: 'IDX_albums_audit_deleted_at' })
+  deletedAt!: Date;
+}
diff --git a/server/src/schema/tables/album-user.table.ts b/server/src/schema/tables/album-user.table.ts
index 8bd05df2ee..abab28df12 100644
--- a/server/src/schema/tables/album-user.table.ts
+++ b/server/src/schema/tables/album-user.table.ts
@@ -1,12 +1,18 @@
 import { AlbumUserRole } from 'src/enum';
+import { album_after_insert } from 'src/schema/functions';
 import { AlbumTable } from 'src/schema/tables/album.table';
 import { UserTable } from 'src/schema/tables/user.table';
-import { Column, ForeignKeyColumn, Index, Table } from 'src/sql-tools';
+import { AfterInsertTrigger, Column, ForeignKeyColumn, Index, Table } from 'src/sql-tools';
 
 @Table({ name: 'albums_shared_users_users', primaryConstraintName: 'PK_7df55657e0b2e8b626330a0ebc8' })
 // Pre-existing indices from original album <--> user ManyToMany mapping
 @Index({ name: 'IDX_427c350ad49bd3935a50baab73', columns: ['albumsId'] })
 @Index({ name: 'IDX_f48513bf9bccefd6ff3ad30bd0', columns: ['usersId'] })
+@AfterInsertTrigger({
+  name: 'albums_after_insert',
+  scope: 'statement',
+  function: album_after_insert,
+})
 export class AlbumUserTable {
   @ForeignKeyColumn(() => AlbumTable, {
     onDelete: 'CASCADE',
diff --git a/server/src/services/sync.service.ts b/server/src/services/sync.service.ts
index 6ad488c48d..389202128c 100644
--- a/server/src/services/sync.service.ts
+++ b/server/src/services/sync.service.ts
@@ -23,13 +23,13 @@ import { fromAck, serialize } from 'src/utils/sync';
 
 const FULL_SYNC = { needsFullSync: true, deleted: [], upserted: [] };
 export const SYNC_TYPES_ORDER = [
-  //
   SyncRequestType.UsersV1,
   SyncRequestType.PartnersV1,
   SyncRequestType.AssetsV1,
   SyncRequestType.AssetExifsV1,
   SyncRequestType.PartnerAssetsV1,
   SyncRequestType.PartnerAssetExifsV1,
+  SyncRequestType.AlbumsV1,
 ];
 
 const throwSessionRequired = () => {
@@ -205,6 +205,23 @@ export class SyncService extends BaseService {
           break;
         }
 
+        case SyncRequestType.AlbumsV1: {
+          // const deletes = this.syncRepository.getAlbumDeletes(
+          //   auth.user.id,
+          //   checkpointMap[SyncEntityType.AlbumDeleteV1],
+          // );
+          // for await (const { id, ...data } of deletes) {
+          //   response.write(serialize({ type: SyncEntityType.AlbumDeleteV1, updateId: id, data }));
+          // }
+
+          const upserts = this.syncRepository.getAlbumUpserts(auth.user.id, checkpointMap[SyncEntityType.AlbumV1]);
+          for await (const { updateId, ...data } of upserts) {
+            response.write(serialize({ type: SyncEntityType.AlbumV1, updateId, data }));
+          }
+
+          break;
+        }
+
         default: {
           this.logger.warn(`Unsupported sync type: ${type}`);
           break;
diff --git a/server/src/sql-tools/from-code/decorators/after-insert.decorator.ts b/server/src/sql-tools/from-code/decorators/after-insert.decorator.ts
new file mode 100644
index 0000000000..103d59b4fc
--- /dev/null
+++ b/server/src/sql-tools/from-code/decorators/after-insert.decorator.ts
@@ -0,0 +1,8 @@
+import { TriggerFunction, TriggerFunctionOptions } from 'src/sql-tools/from-code/decorators/trigger-function.decorator';
+
+export const AfterInsertTrigger = (options: Omit<TriggerFunctionOptions, 'timing' | 'actions'>) =>
+  TriggerFunction({
+    timing: 'after',
+    actions: ['insert'],
+    ...options,
+  });
diff --git a/server/src/sql-tools/public_api.ts b/server/src/sql-tools/public_api.ts
index b41cce4ab5..c7a3023a4d 100644
--- a/server/src/sql-tools/public_api.ts
+++ b/server/src/sql-tools/public_api.ts
@@ -1,6 +1,7 @@
 export { schemaDiff } from 'src/sql-tools/diff';
 export { schemaFromCode } from 'src/sql-tools/from-code';
 export * from 'src/sql-tools/from-code/decorators/after-delete.decorator';
+export * from 'src/sql-tools/from-code/decorators/after-insert.decorator';
 export * from 'src/sql-tools/from-code/decorators/before-update.decorator';
 export * from 'src/sql-tools/from-code/decorators/check.decorator';
 export * from 'src/sql-tools/from-code/decorators/column.decorator';
diff --git a/server/test/medium.factory.ts b/server/test/medium.factory.ts
index 6f4f46c075..4ff593eaac 100644
--- a/server/test/medium.factory.ts
+++ b/server/test/medium.factory.ts
@@ -4,9 +4,10 @@ import { DateTime } from 'luxon';
 import { createHash, randomBytes } from 'node:crypto';
 import { Writable } from 'node:stream';
 import { AssetFace } from 'src/database';
-import { AssetJobStatus, Assets, DB, FaceSearch, Person, Sessions } from 'src/db';
+import { Albums, AssetJobStatus, Assets, DB, FaceSearch, Person, Sessions } from 'src/db';
 import { AssetType, AssetVisibility, SourceType } from 'src/enum';
 import { ActivityRepository } from 'src/repositories/activity.repository';
+import { AlbumUserRepository } from 'src/repositories/album-user.repository';
 import { AlbumRepository } from 'src/repositories/album.repository';
 import { AssetJobRepository } from 'src/repositories/asset-job.repository';
 import { AssetRepository } from 'src/repositories/asset.repository';
@@ -39,6 +40,7 @@ const sha256 = (value: string) => createHash('sha256').update(value).digest('bas
 type RepositoriesTypes = {
   activity: ActivityRepository;
   album: AlbumRepository;
+  albumUser: AlbumUserRepository;
   asset: AssetRepository;
   assetJob: AssetJobRepository;
   config: ConfigRepository;
@@ -125,6 +127,14 @@ export const getRepository = <K extends keyof RepositoriesTypes>(key: K, db: Kys
       return new ActivityRepository(db);
     }
 
+    case 'album': {
+      return new AlbumRepository(db);
+    }
+
+    case 'albumUser': {
+      return new AlbumUserRepository(db);
+    }
+
     case 'asset': {
       return new AssetRepository(db);
     }
@@ -380,6 +390,19 @@ const assetInsert = (asset: Partial<Insertable<Assets>> = {}) => {
   };
 };
 
+const albumInsert = (album: Partial<Insertable<Albums>> & { ownerId: string }) => {
+  const id = album.id || newUuid();
+  const defaults: Omit<Insertable<Albums>, 'ownerId'> = {
+    albumName: 'Album',
+  };
+
+  return {
+    ...defaults,
+    ...album,
+    id,
+  };
+};
+
 const faceInsert = (face: Partial<Insertable<FaceSearch>> & { faceId: string }) => {
   const defaults = {
     faceId: face.faceId,
@@ -502,6 +525,7 @@ export const mediumFactory = {
   assetInsert,
   assetFaceInsert,
   assetJobStatusInsert,
+  albumInsert,
   faceInsert,
   personInsert,
   sessionInsert,
diff --git a/server/test/medium/specs/services/sync.service.spec.ts b/server/test/medium/specs/services/sync.service.spec.ts
index 67cfeafdbf..7e0bdfa916 100644
--- a/server/test/medium/specs/services/sync.service.spec.ts
+++ b/server/test/medium/specs/services/sync.service.spec.ts
@@ -1,5 +1,5 @@
 import { AuthDto } from 'src/dtos/auth.dto';
-import { SyncEntityType, SyncRequestType } from 'src/enum';
+import { AlbumUserRole, SyncEntityType, SyncRequestType } from 'src/enum';
 import { SYNC_TYPES_ORDER, SyncService } from 'src/services/sync.service';
 import { mediumFactory, newMediumService } from 'test/medium.factory';
 import { factory } from 'test/small.factory';
@@ -907,4 +907,124 @@ describe(SyncService.name, () => {
       await expect(testSync(auth, [SyncRequestType.PartnerAssetExifsV1])).resolves.toHaveLength(0);
     });
   });
+
+  describe.concurrent(SyncRequestType.AlbumsV1, () => {
+    it('should sync an album with the correct properties', async () => {
+      const { auth, getRepository, testSync } = await setup();
+      const albumRepo = getRepository('album');
+      const album = mediumFactory.albumInsert({ ownerId: auth.user.id });
+      await albumRepo.create(album, [], []);
+      await expect(testSync(auth, [SyncRequestType.AlbumsV1])).resolves.toEqual([
+        {
+          ack: expect.any(String),
+          data: expect.objectContaining({
+            id: album.id,
+            name: album.albumName,
+            ownerId: album.ownerId,
+          }),
+          type: SyncEntityType.AlbumV1,
+        },
+      ]);
+    });
+
+    it('should detect and sync a new album', async () => {
+      const { auth, getRepository, testSync } = await setup();
+      const albumRepo = getRepository('album');
+      const album = mediumFactory.albumInsert({ ownerId: auth.user.id });
+      await albumRepo.create(album, [], []);
+      await expect(testSync(auth, [SyncRequestType.AlbumsV1])).resolves.toEqual([
+        {
+          ack: expect.any(String),
+          data: expect.objectContaining({
+            id: album.id,
+          }),
+          type: SyncEntityType.AlbumV1,
+        },
+      ]);
+    });
+
+    describe('shared albums', () => {
+      it('should detect and sync an album create', async () => {
+        const { auth, getRepository, testSync } = await setup();
+        const albumRepo = getRepository('album');
+        const userRepo = getRepository('user');
+
+        const user2 = mediumFactory.userInsert();
+        await userRepo.create(user2);
+
+        const album = mediumFactory.albumInsert({ ownerId: user2.id });
+        await albumRepo.create(album, [], [{ userId: auth.user.id, role: AlbumUserRole.EDITOR }]);
+
+        await expect(testSync(auth, [SyncRequestType.AlbumsV1])).resolves.toEqual([
+          {
+            ack: expect.any(String),
+            data: expect.objectContaining({ id: album.id }),
+            type: SyncEntityType.AlbumV1,
+          },
+        ]);
+      });
+
+      it('should detect and sync an recently shared album', async () => {
+        const { auth, getRepository, testSync } = await setup();
+        const albumRepo = getRepository('album');
+        const albumUserRepo = getRepository('albumUser');
+        const userRepo = getRepository('user');
+
+        const user2 = mediumFactory.userInsert();
+        await userRepo.create(user2);
+
+        const album = mediumFactory.albumInsert({ ownerId: user2.id });
+        await albumRepo.create(album, [], []);
+        await albumUserRepo.create({ usersId: auth.user.id, albumsId: album.id, role: AlbumUserRole.EDITOR });
+
+        await expect(testSync(auth, [SyncRequestType.AlbumsV1])).resolves.toEqual([
+          {
+            ack: expect.any(String),
+            data: expect.objectContaining({ id: album.id }),
+            type: SyncEntityType.AlbumV1,
+          },
+        ]);
+      });
+
+      it('should handle sharing an album that was created before the last the sync', async () => {
+        const { auth, getRepository, sut, testSync } = await setup();
+        const albumRepo = getRepository('album');
+        const albumUserRepo = getRepository('albumUser');
+        const userRepo = getRepository('user');
+
+        const user2 = mediumFactory.userInsert();
+        await userRepo.create(user2);
+
+        const userAlbum = mediumFactory.albumInsert({ ownerId: auth.user.id });
+        const user2Album = mediumFactory.albumInsert({ ownerId: user2.id });
+        await Promise.all([albumRepo.create(user2Album, [], []), albumRepo.create(userAlbum, [], [])]);
+
+        const initialSyncResponse = await testSync(auth, [SyncRequestType.AlbumsV1]);
+
+        expect(initialSyncResponse).toEqual([
+          {
+            ack: expect.any(String),
+            data: expect.objectContaining({ id: userAlbum.id }),
+            type: SyncEntityType.AlbumV1,
+          },
+        ]);
+
+        const acks = [initialSyncResponse[0].ack];
+        await sut.setAcks(auth, { acks });
+
+        await albumUserRepo.create({ usersId: auth.user.id, albumsId: user2Album.id, role: AlbumUserRole.EDITOR });
+
+        await expect(testSync(auth, [SyncRequestType.AlbumsV1])).resolves.toEqual([
+          {
+            ack: expect.any(String),
+            data: expect.objectContaining({ id: user2Album.id }),
+            type: SyncEntityType.AlbumV1,
+          },
+        ]);
+      });
+    });
+  });
+
+  // describe.concurrent(SyncRequestType.AlbumsV1, () => {
+  // });
 });