diff --git a/packages/sanity/src/core/releases/components/BundleMenuButton/BundleMenuButton.tsx b/packages/sanity/src/core/releases/components/BundleMenuButton/BundleMenuButton.tsx
index 041a2c3c97a6..e02e3e38eb1f 100644
--- a/packages/sanity/src/core/releases/components/BundleMenuButton/BundleMenuButton.tsx
+++ b/packages/sanity/src/core/releases/components/BundleMenuButton/BundleMenuButton.tsx
@@ -1,5 +1,4 @@
-/* eslint-disable @sanity/i18n/no-attribute-string-literals */
-import {EllipsisHorizontalIcon, TrashIcon} from '@sanity/icons'
+import {ArchiveIcon, EllipsisHorizontalIcon, TrashIcon} from '@sanity/icons'
 import {Button, Menu, MenuButton, MenuItem, Spinner} from '@sanity/ui'
 import {useState} from 'react'
 import {useRouter} from 'sanity/router'
@@ -12,8 +11,9 @@ type Props = {
 }
 
 export const BundleMenuButton = ({bundle}: Props) => {
-  const {deleteBundle} = useBundleOperations()
+  const {deleteBundle, updateBundle} = useBundleOperations()
   const router = useRouter()
+  const isBundleArchived = !!bundle?.archivedAt
   const [isPerformingOperation, setIsPerformingOperation] = useState(false)
 
   const bundleMenuDisabled = !bundle
@@ -30,11 +30,22 @@ export const BundleMenuButton = ({bundle}: Props) => {
     }
   }
 
+  const handleOnToggleArchive = async () => {
+    if (bundleMenuDisabled) return
+
+    setIsPerformingOperation(true)
+    await updateBundle({
+      ...bundle,
+      archivedAt: isBundleArchived ? undefined : new Date().toISOString(),
+    })
+    setIsPerformingOperation(false)
+  }
+
   return (
     <MenuButton
       button={
         <Button
-          disabled={bundleMenuDisabled}
+          disabled={bundleMenuDisabled || isPerformingOperation}
           icon={isPerformingOperation ? Spinner : EllipsisHorizontalIcon}
           mode="bleed"
           padding={2}
@@ -44,7 +55,14 @@ export const BundleMenuButton = ({bundle}: Props) => {
       id="bundle-menu"
       menu={
         <Menu>
-          <MenuItem onClick={handleOnDeleteBundle} icon={TrashIcon} text="Delete release" />
+          <MenuItem
+            onClick={handleOnToggleArchive}
+            // TODO: swap line once UnaryIcon is available
+            // icon={isBundleArchived ? UnarchiveIcon : ArchiveIcon}
+            icon={isBundleArchived ? ArchiveIcon : ArchiveIcon}
+            text={isBundleArchived ? 'Unarchive' : 'Archive'}
+          />
+          <MenuItem onClick={handleOnDeleteBundle} icon={TrashIcon} text="Delete" />
         </Menu>
       }
       popover={{
diff --git a/packages/sanity/src/core/releases/components/BundleMenuButton/__tests__/BundleMenuButton.test.tsx b/packages/sanity/src/core/releases/components/BundleMenuButton/__tests__/BundleMenuButton.test.tsx
new file mode 100644
index 000000000000..113c3e6384fd
--- /dev/null
+++ b/packages/sanity/src/core/releases/components/BundleMenuButton/__tests__/BundleMenuButton.test.tsx
@@ -0,0 +1,108 @@
+import {describe, expect, jest, test} from '@jest/globals'
+import {fireEvent, render, screen} from '@testing-library/react'
+import {act} from 'react'
+import {useRouter} from 'sanity/router'
+
+import {createTestProvider} from '../../../../../../test/testUtils/TestProvider'
+import {type BundleDocument} from '../../../../store/bundles/types'
+import {useBundleOperations} from '../../../../store/bundles/useBundleOperations'
+import {releasesUsEnglishLocaleBundle} from '../../../i18n'
+import {BundleMenuButton} from '../BundleMenuButton'
+
+jest.mock('../../../../store/bundles/useBundleOperations', () => ({
+  useBundleOperations: jest.fn().mockReturnValue({
+    deleteBundle: jest.fn(),
+    updateBundle: jest.fn(),
+  }),
+}))
+
+jest.mock('sanity/router', () => ({
+  ...(jest.requireActual('sanity/router') || {}),
+  useRouter: jest.fn().mockReturnValue({state: {}, navigate: jest.fn()}),
+}))
+
+const renderTest = async (bundle: BundleDocument) => {
+  const wrapper = await createTestProvider({
+    resources: [releasesUsEnglishLocaleBundle],
+  })
+  return render(<BundleMenuButton bundle={bundle} />, {wrapper})
+}
+
+describe('BundleMenuButton', () => {
+  test('will archive an unarchived bundle', async () => {
+    const activeBundle: BundleDocument = {
+      _id: 'activeBundle',
+      _type: 'bundle',
+      archivedAt: undefined,
+      title: 'activeBundle',
+      name: 'activeBundle',
+      authorId: 'author',
+      _createdAt: new Date().toISOString(),
+      _updatedAt: new Date().toISOString(),
+      _rev: '',
+    }
+
+    await renderTest(activeBundle)
+
+    fireEvent.click(screen.getByLabelText('Release menu'))
+
+    await act(() => {
+      fireEvent.click(screen.getByText('Archive'))
+    })
+
+    expect(useBundleOperations().updateBundle).toHaveBeenCalledWith({
+      ...activeBundle,
+      archivedAt: expect.any(String),
+    })
+  })
+
+  test('will unarchive an archived bundle', async () => {
+    const archivedBundle: BundleDocument = {
+      _id: 'activeBundle',
+      _type: 'bundle',
+      archivedAt: new Date().toISOString(),
+      title: 'activeBundle',
+      name: 'activeBundle',
+      authorId: 'author',
+      _createdAt: new Date().toISOString(),
+      _updatedAt: new Date().toISOString(),
+      _rev: '',
+    }
+    await renderTest(archivedBundle)
+
+    fireEvent.click(screen.getByLabelText('Release menu'))
+
+    await act(() => {
+      fireEvent.click(screen.getByText('Unarchive'))
+    })
+
+    expect(useBundleOperations().updateBundle).toHaveBeenCalledWith({
+      ...archivedBundle,
+      archivedAt: undefined,
+    })
+  })
+
+  test('will delete a bundle', async () => {
+    const activeBundle: BundleDocument = {
+      _id: 'activeBundle',
+      _type: 'bundle',
+      archivedAt: new Date().toISOString(),
+      title: 'activeBundle',
+      name: 'activeBundle',
+      authorId: 'author',
+      _createdAt: new Date().toISOString(),
+      _updatedAt: new Date().toISOString(),
+      _rev: '',
+    }
+    await renderTest(activeBundle)
+
+    fireEvent.click(screen.getByLabelText('Release menu'))
+
+    await act(() => {
+      fireEvent.click(screen.getByText('Delete'))
+    })
+
+    expect(useBundleOperations().deleteBundle).toHaveBeenCalledWith(activeBundle._id)
+    expect(useRouter().navigate).not.toHaveBeenCalled()
+  })
+})
diff --git a/packages/sanity/src/core/releases/components/BundlesTable/BundleRow.tsx b/packages/sanity/src/core/releases/components/BundlesTable/BundleRow.tsx
index cc662af812f6..188531780fa9 100644
--- a/packages/sanity/src/core/releases/components/BundlesTable/BundleRow.tsx
+++ b/packages/sanity/src/core/releases/components/BundlesTable/BundleRow.tsx
@@ -2,7 +2,7 @@ import {Box, Card, Flex, Stack, Text} from '@sanity/ui'
 import {useRouter} from 'sanity/router'
 
 import {BundleBadge} from '../../../bundles/components/BundleBadge'
-import {RelativeTime} from '../../../components/RelativeTime'
+import {RelativeTime} from '../../../components'
 import {type BundleDocument} from '../../../store/bundles/types'
 import {BundleMenuButton} from '../BundleMenuButton/BundleMenuButton'
 
diff --git a/packages/sanity/src/core/releases/components/BundlesTable/BundlesTable.tsx b/packages/sanity/src/core/releases/components/BundlesTable/BundlesTable.tsx
index 5b347c821cce..f9ae26b47fb9 100644
--- a/packages/sanity/src/core/releases/components/BundlesTable/BundlesTable.tsx
+++ b/packages/sanity/src/core/releases/components/BundlesTable/BundlesTable.tsx
@@ -1,4 +1,3 @@
-/* eslint-disable i18next/no-literal-string */
 import {Card, Stack, Text} from '@sanity/ui'
 import {useMemo} from 'react'
 import {styled} from 'styled-components'
@@ -51,7 +50,7 @@ export function BundlesTable({bundles, searchTerm, setSearchTerm}: BundlesTableP
   return (
     <Stack as="table" space={1}>
       <BundleHeader
-        searchDisabled={!bundles.length}
+        searchDisabled={!searchTerm && !bundles.length}
         searchTerm={searchTerm}
         setSearchTerm={setSearchTerm}
       />
diff --git a/packages/sanity/src/core/releases/components/BundlesTable/__tests__/BundlesTable.test.tsx b/packages/sanity/src/core/releases/components/BundlesTable/__tests__/BundlesTable.test.tsx
index f6eec626ff7f..fe70025b0a7f 100644
--- a/packages/sanity/src/core/releases/components/BundlesTable/__tests__/BundlesTable.test.tsx
+++ b/packages/sanity/src/core/releases/components/BundlesTable/__tests__/BundlesTable.test.tsx
@@ -83,7 +83,7 @@ describe('BundlesTable', () => {
       const bundleRow = screen.getAllByTestId('bundle-row')[0]
       fireEvent.click(within(bundleRow).getByLabelText('Release menu'))
 
-      fireEvent.click(screen.getByText('Delete release'))
+      fireEvent.click(screen.getByText('Delete'))
 
       await waitFor(() => {
         expect(useBundleOperations().deleteBundle).toHaveBeenCalledWith('123')
diff --git a/packages/sanity/src/core/releases/tool/BundlesOverview.tsx b/packages/sanity/src/core/releases/tool/BundlesOverview.tsx
index b047127074ff..42c896574412 100644
--- a/packages/sanity/src/core/releases/tool/BundlesOverview.tsx
+++ b/packages/sanity/src/core/releases/tool/BundlesOverview.tsx
@@ -1,7 +1,7 @@
 import {AddIcon} from '@sanity/icons'
 import {Box, Button, type ButtonMode, Card, Container, Flex, Heading, Stack, Text} from '@sanity/ui'
 import {isBefore} from 'date-fns'
-import {type MouseEventHandler, useCallback, useMemo, useState} from 'react'
+import {type MouseEventHandler, useCallback, useEffect, useMemo, useState} from 'react'
 
 import {Button as StudioButton} from '../../../ui-components'
 import {CreateBundleDialog} from '../../bundles/components/dialog/CreateBundleDialog'
@@ -28,19 +28,28 @@ export default function BundlesOverview() {
   const groupedBundles = useMemo(
     () =>
       data?.reduce<{open: BundleDocument[]; archived: BundleDocument[]}>((groups, bundle) => {
-        const group =
-          bundle.publishedAt && isBefore(new Date(bundle.publishedAt), new Date())
-            ? 'archived'
-            : 'open'
+        const isBundleArchived =
+          bundle.archivedAt ||
+          (bundle.publishedAt && isBefore(new Date(bundle.publishedAt), new Date()))
+        const group = isBundleArchived ? 'archived' : 'open'
 
         return {...groups, [group]: [...groups[group], bundle]}
       }, EMPTY_BUNDLE_GROUPS) || EMPTY_BUNDLE_GROUPS,
     [data],
   )
 
+  // switch to open mode if on archived mode and there are no archived bundles
+  useEffect(() => {
+    if (bundleGroupMode === 'archived' && !groupedBundles.archived.length) {
+      setBundleGroupMode('open')
+    }
+  }, [bundleGroupMode, groupedBundles.archived.length])
+
+  // clear search when mode changes
+  useEffect(() => setSearchTerm(''), [bundleGroupMode])
+
   const handleBundleGroupModeChange = useCallback<MouseEventHandler<HTMLButtonElement>>(
     ({currentTarget: {value: groupMode}}) => {
-      setSearchTerm('') // clear the table search applied
       setBundleGroupMode(groupMode as Mode)
     },
     [],
@@ -111,7 +120,8 @@ export default function BundlesOverview() {
   }
 
   const applySearchTermToBundles = useCallback(
-    (bundle: BundleDocument) => !searchTerm || bundle.title.includes(searchTerm),
+    (bundle: BundleDocument) =>
+      !searchTerm || bundle.title.toLocaleLowerCase().includes(searchTerm.toLocaleLowerCase()),
     [searchTerm],
   )
 
diff --git a/packages/sanity/src/core/releases/tool/__tests__/BundlesOverview.test.tsx b/packages/sanity/src/core/releases/tool/__tests__/BundlesOverview.test.tsx
index d8a266a154a9..1d87ac029fb0 100644
--- a/packages/sanity/src/core/releases/tool/__tests__/BundlesOverview.test.tsx
+++ b/packages/sanity/src/core/releases/tool/__tests__/BundlesOverview.test.tsx
@@ -1,5 +1,5 @@
 import {beforeEach, describe, expect, it, jest} from '@jest/globals'
-import {fireEvent, render, screen} from '@testing-library/react'
+import {fireEvent, render, screen, waitFor} from '@testing-library/react'
 import {type ReactNode} from 'react'
 
 import {queryByDataUi} from '../../../../../test/setup/customQueries'
@@ -108,7 +108,8 @@ describe('BundlesOverview', () => {
     const bundles = [
       {title: 'Bundle 1'},
       {title: 'Bundle 2'},
-      {title: 'Bundle 3', publishedAt: new Date()},
+      {title: 'Bundle 3', publishedAt: new Date().toISOString()},
+      {title: 'Bundle 4', archivedAt: new Date().toISOString()},
     ] as unknown as BundleDocument[]
 
     beforeEach(async () => {
@@ -132,11 +133,14 @@ describe('BundlesOverview', () => {
       expect(screen.getByText('Archived').closest('button')).not.toBeDisabled()
     })
 
-    it('shows published bundles', () => {
+    it('shows published bundles', async () => {
       fireEvent.click(screen.getByText('Archived'))
 
-      screen.getByText('Bundle 3')
-      expect(screen.queryByText('Bundle 1')).toBeNull()
+      await waitFor(() => {
+        screen.getByText('Bundle 3')
+        screen.getByText('Bundle 4')
+        expect(screen.queryByText('Bundle 1')).toBeNull()
+      })
     })
 
     it('allows for searching bundles', () => {
diff --git a/packages/sanity/src/core/store/bundles/types.ts b/packages/sanity/src/core/store/bundles/types.ts
index ffd7edc1c4e8..fd9121b09548 100644
--- a/packages/sanity/src/core/store/bundles/types.ts
+++ b/packages/sanity/src/core/store/bundles/types.ts
@@ -14,6 +14,7 @@ export interface BundleDocument extends SanityDocument {
   icon?: IconSymbol
   authorId: string
   publishedAt?: string
+  archivedAt?: string
 }
 
 /**
diff --git a/packages/sanity/src/core/store/bundles/useBundleOperations.ts b/packages/sanity/src/core/store/bundles/useBundleOperations.ts
index 7d37cc1d78b0..22fef24c2b47 100644
--- a/packages/sanity/src/core/store/bundles/useBundleOperations.ts
+++ b/packages/sanity/src/core/store/bundles/useBundleOperations.ts
@@ -31,13 +31,22 @@ export function useBundleOperations() {
 
   const handleUpdateBundle = useCallback(
     async (bundle: BundleDocument) => {
+      if (!client) return null
+
       const document = {
         ...bundle,
         _type: 'bundle',
       } as BundleDocument
+      const unsetKeys = Object.entries(bundle)
+        .filter(([_, value]) => value === undefined)
+        .map(([key]) => key)
 
-      const res = await client?.patch(bundle._id).set(document).commit()
-      return res
+      let clientOperation = client.patch(bundle._id).set(document)
+      if (unsetKeys.length) {
+        clientOperation = clientOperation.unset(unsetKeys)
+      }
+
+      return clientOperation.commit()
     },
     [client],
   )