diff --git a/modules/indexer/issues/bleve/bleve.go b/modules/indexer/issues/bleve/bleve.go
index 7ef370e89c..bf51bd6c14 100644
--- a/modules/indexer/issues/bleve/bleve.go
+++ b/modules/indexer/issues/bleve/bleve.go
@@ -23,7 +23,7 @@ import (
 const (
 	issueIndexerAnalyzer      = "issueIndexer"
 	issueIndexerDocType       = "issueIndexerDocType"
-	issueIndexerLatestVersion = 4
+	issueIndexerLatestVersion = 5
 )
 
 const unicodeNormalizeName = "unicodeNormalize"
@@ -75,6 +75,7 @@ func generateIssueIndexMapping() (mapping.IndexMapping, error) {
 
 	docMapping.AddFieldMappingsAt("is_pull", boolFieldMapping)
 	docMapping.AddFieldMappingsAt("is_closed", boolFieldMapping)
+	docMapping.AddFieldMappingsAt("is_archived", boolFieldMapping)
 	docMapping.AddFieldMappingsAt("label_ids", numberFieldMapping)
 	docMapping.AddFieldMappingsAt("no_label", boolFieldMapping)
 	docMapping.AddFieldMappingsAt("milestone_id", numberFieldMapping)
@@ -185,6 +186,9 @@ func (b *Indexer) Search(ctx context.Context, options *internal.SearchOptions) (
 	if options.IsClosed.Has() {
 		queries = append(queries, inner_bleve.BoolFieldQuery(options.IsClosed.Value(), "is_closed"))
 	}
+	if options.IsArchived.Has() {
+		queries = append(queries, inner_bleve.BoolFieldQuery(options.IsArchived.Value(), "is_archived"))
+	}
 
 	if options.NoLabelOnly {
 		queries = append(queries, inner_bleve.BoolFieldQuery(true, "no_label"))
diff --git a/modules/indexer/issues/db/options.go b/modules/indexer/issues/db/options.go
index 98b097f871..42834f6e88 100644
--- a/modules/indexer/issues/db/options.go
+++ b/modules/indexer/issues/db/options.go
@@ -72,7 +72,7 @@ func ToDBOptions(ctx context.Context, options *internal.SearchOptions) (*issue_m
 		UpdatedAfterUnix:   options.UpdatedAfterUnix.Value(),
 		UpdatedBeforeUnix:  options.UpdatedBeforeUnix.Value(),
 		PriorityRepoID:     0,
-		IsArchived:         optional.None[bool](),
+		IsArchived:         options.IsArchived,
 		Org:                nil,
 		Team:               nil,
 		User:               nil,
diff --git a/modules/indexer/issues/dboptions.go b/modules/indexer/issues/dboptions.go
index 1a0f241e61..4f6ad96d22 100644
--- a/modules/indexer/issues/dboptions.go
+++ b/modules/indexer/issues/dboptions.go
@@ -11,11 +11,12 @@ import (
 
 func ToSearchOptions(keyword string, opts *issues_model.IssuesOptions) *SearchOptions {
 	searchOpt := &SearchOptions{
-		Keyword:   keyword,
-		RepoIDs:   opts.RepoIDs,
-		AllPublic: opts.AllPublic,
-		IsPull:    opts.IsPull,
-		IsClosed:  opts.IsClosed,
+		Keyword:    keyword,
+		RepoIDs:    opts.RepoIDs,
+		AllPublic:  opts.AllPublic,
+		IsPull:     opts.IsPull,
+		IsClosed:   opts.IsClosed,
+		IsArchived: opts.IsArchived,
 	}
 
 	if len(opts.LabelIDs) == 1 && opts.LabelIDs[0] == 0 {
diff --git a/modules/indexer/issues/elasticsearch/elasticsearch.go b/modules/indexer/issues/elasticsearch/elasticsearch.go
index 6f70515009..4c293f3f2a 100644
--- a/modules/indexer/issues/elasticsearch/elasticsearch.go
+++ b/modules/indexer/issues/elasticsearch/elasticsearch.go
@@ -18,7 +18,7 @@ import (
 )
 
 const (
-	issueIndexerLatestVersion = 1
+	issueIndexerLatestVersion = 2
 	// multi-match-types, currently only 2 types are used
 	// Reference: https://www.elastic.co/guide/en/elasticsearch/reference/7.0/query-dsl-multi-match-query.html#multi-match-types
 	esMultiMatchTypeBestFields   = "best_fields"
@@ -58,6 +58,7 @@ const (
 
 			"is_pull": { "type": "boolean", "index": true },
 			"is_closed": { "type": "boolean", "index": true },
+			"is_archived": { "type": "boolean", "index": true },
 			"label_ids": { "type": "integer", "index": true },
 			"no_label": { "type": "boolean", "index": true },
 			"milestone_id": { "type": "integer", "index": true },
@@ -168,6 +169,9 @@ func (b *Indexer) Search(ctx context.Context, options *internal.SearchOptions) (
 	if options.IsClosed.Has() {
 		query.Must(elastic.NewTermQuery("is_closed", options.IsClosed.Value()))
 	}
+	if options.IsArchived.Has() {
+		query.Must(elastic.NewTermQuery("is_archived", options.IsArchived.Value()))
+	}
 
 	if options.NoLabelOnly {
 		query.Must(elastic.NewTermQuery("no_label", true))
diff --git a/modules/indexer/issues/indexer_test.go b/modules/indexer/issues/indexer_test.go
index 7c3ba75bb0..06a6a46c23 100644
--- a/modules/indexer/issues/indexer_test.go
+++ b/modules/indexer/issues/indexer_test.go
@@ -37,6 +37,7 @@ func TestDBSearchIssues(t *testing.T) {
 	t.Run("search issues by ID", searchIssueByID)
 	t.Run("search issues is pr", searchIssueIsPull)
 	t.Run("search issues is closed", searchIssueIsClosed)
+	t.Run("search issues is archived", searchIssueIsArchived)
 	t.Run("search issues by milestone", searchIssueByMilestoneID)
 	t.Run("search issues by label", searchIssueByLabelID)
 	t.Run("search issues by time", searchIssueByTime)
@@ -298,6 +299,33 @@ func searchIssueIsClosed(t *testing.T) {
 	}
 }
 
+func searchIssueIsArchived(t *testing.T) {
+	tests := []struct {
+		opts        SearchOptions
+		expectedIDs []int64
+	}{
+		{
+			SearchOptions{
+				IsArchived: optional.Some(false),
+			},
+			[]int64{22, 21, 17, 16, 15, 13, 12, 11, 20, 6, 5, 19, 18, 10, 7, 4, 9, 8, 3, 2, 1},
+		},
+		{
+			SearchOptions{
+				IsArchived: optional.Some(true),
+			},
+			[]int64{14},
+		},
+	}
+	for _, test := range tests {
+		issueIDs, _, err := SearchIssues(context.TODO(), &test.opts)
+		if !assert.NoError(t, err) {
+			return
+		}
+		assert.Equal(t, test.expectedIDs, issueIDs)
+	}
+}
+
 func searchIssueByMilestoneID(t *testing.T) {
 	tests := []struct {
 		opts        SearchOptions
diff --git a/modules/indexer/issues/internal/model.go b/modules/indexer/issues/internal/model.go
index a43c6be005..09dcbf4804 100644
--- a/modules/indexer/issues/internal/model.go
+++ b/modules/indexer/issues/internal/model.go
@@ -25,6 +25,7 @@ type IndexerData struct {
 	// Fields used for filtering
 	IsPull             bool               `json:"is_pull"`
 	IsClosed           bool               `json:"is_closed"`
+	IsArchived         bool               `json:"is_archived"`
 	LabelIDs           []int64            `json:"label_ids"`
 	NoLabel            bool               `json:"no_label"` // True if LabelIDs is empty
 	MilestoneID        int64              `json:"milestone_id"`
@@ -81,8 +82,9 @@ type SearchOptions struct {
 	RepoIDs   []int64 // repository IDs which the issues belong to
 	AllPublic bool    // if include all public repositories
 
-	IsPull   optional.Option[bool] // if the issues is a pull request
-	IsClosed optional.Option[bool] // if the issues is closed
+	IsPull     optional.Option[bool] // if the issues is a pull request
+	IsClosed   optional.Option[bool] // if the issues is closed
+	IsArchived optional.Option[bool] // if the repo is archived
 
 	IncludedLabelIDs    []int64 // labels the issues have
 	ExcludedLabelIDs    []int64 // labels the issues don't have
diff --git a/modules/indexer/issues/meilisearch/meilisearch.go b/modules/indexer/issues/meilisearch/meilisearch.go
index 9332319339..1066e96272 100644
--- a/modules/indexer/issues/meilisearch/meilisearch.go
+++ b/modules/indexer/issues/meilisearch/meilisearch.go
@@ -18,7 +18,7 @@ import (
 )
 
 const (
-	issueIndexerLatestVersion = 3
+	issueIndexerLatestVersion = 4
 
 	// TODO: make this configurable if necessary
 	maxTotalHits = 10000
@@ -61,6 +61,7 @@ func NewIndexer(url, apiKey, indexerName string) *Indexer {
 			"is_public",
 			"is_pull",
 			"is_closed",
+			"is_archived",
 			"label_ids",
 			"no_label",
 			"milestone_id",
@@ -145,6 +146,9 @@ func (b *Indexer) Search(ctx context.Context, options *internal.SearchOptions) (
 	if options.IsClosed.Has() {
 		query.And(inner_meilisearch.NewFilterEq("is_closed", options.IsClosed.Value()))
 	}
+	if options.IsArchived.Has() {
+		query.And(inner_meilisearch.NewFilterEq("is_archived", options.IsArchived.Value()))
+	}
 
 	if options.NoLabelOnly {
 		query.And(inner_meilisearch.NewFilterEq("no_label", true))
diff --git a/modules/indexer/issues/util.go b/modules/indexer/issues/util.go
index e752ae6f24..deb19adc49 100644
--- a/modules/indexer/issues/util.go
+++ b/modules/indexer/issues/util.go
@@ -101,6 +101,7 @@ func getIssueIndexerData(ctx context.Context, issueID int64) (*internal.IndexerD
 		Comments:           comments,
 		IsPull:             issue.IsPull,
 		IsClosed:           issue.IsClosed,
+		IsArchived:         issue.Repo.IsArchived,
 		LabelIDs:           labels,
 		NoLabel:            len(labels) == 0,
 		MilestoneID:        issue.MilestoneID,
diff --git a/routers/web/repo/setting/setting.go b/routers/web/repo/setting/setting.go
index e30129bb44..717d7cbce1 100644
--- a/routers/web/repo/setting/setting.go
+++ b/routers/web/repo/setting/setting.go
@@ -22,6 +22,7 @@ import (
 	"code.gitea.io/gitea/modules/base"
 	"code.gitea.io/gitea/modules/git"
 	"code.gitea.io/gitea/modules/indexer/code"
+	issue_indexer "code.gitea.io/gitea/modules/indexer/issues"
 	"code.gitea.io/gitea/modules/indexer/stats"
 	"code.gitea.io/gitea/modules/lfs"
 	"code.gitea.io/gitea/modules/log"
@@ -905,6 +906,9 @@ func SettingsPost(ctx *context.Context) {
 			log.Error("CleanRepoScheduleTasks for archived repo %s/%s: %v", ctx.Repo.Owner.Name, repo.Name, err)
 		}
 
+		// update issue indexer
+		issue_indexer.UpdateRepoIndexer(ctx, repo.ID)
+
 		ctx.Flash.Success(ctx.Tr("repo.settings.archive.success"))
 
 		log.Trace("Repository was archived: %s/%s", ctx.Repo.Owner.Name, repo.Name)
@@ -929,6 +933,9 @@ func SettingsPost(ctx *context.Context) {
 			}
 		}
 
+		// update issue indexer
+		issue_indexer.UpdateRepoIndexer(ctx, repo.ID)
+
 		ctx.Flash.Success(ctx.Tr("repo.settings.unarchive.success"))
 
 		log.Trace("Repository was un-archived: %s/%s", ctx.Repo.Owner.Name, repo.Name)