gitlab-org/gitlab
Search
GitLab has three search backends layered on top of Postgres trigram search.
Backends
| Backend | What it indexes | Source |
|---|---|---|
| Postgres trigram | Issues, MRs, snippets when no ES is configured | inline ActiveRecord scopes |
| Elasticsearch | Full-text issues, MRs, comments, code (legacy) | ee/lib/elastic/, ee/lib/api/internal/elastic/ |
| Zoekt | Code search (high-scale) | ee/lib/search/zoekt/, ee/lib/api/internal/search/zoekt/ |
| Active Context (vector) | Embeddings for retrieval and chat | ee/lib/active_context/, gems/gitlab-active-context/ |
Source layout
app/services/search/
├── group_service.rb
├── project_service.rb
├── snippet_service.rb
└── ...
app/finders/issues_finder.rb (and friends) # PG search fallback
lib/gitlab/search/
├── query_normalizer.rb
└── ...
ee/lib/elastic/ # Elasticsearch indexing & query
ee/lib/search/zoekt/ # Zoekt indexing & query
ee/lib/active_context/ # Vector retrieval framework
ee/app/workers/elastic/ # Indexing workers
ee/app/workers/search/ # Cross-backend search workersHigh-level flow
graph TD
User -->|/search?q=...| Ctrl[SearchController]
Ctrl --> SS[SearchService]
SS --> Strat[Strategy resolver]
Strat -->|advanced search| ES[Elasticsearch]
Strat -->|code| Zoekt[Zoekt]
Strat -->|fallback| PG[(Postgres)]
ES --> Idx[gitlab-elasticsearch-indexer]
Zoekt --> ZIdx[gitlab-zoekt-indexer]Elasticsearch
The legacy advanced search uses Elasticsearch for issues, MRs, comments, wikis, and code (in projects below a size threshold).
- Indexing is driven by Sidekiq workers in
ee/app/workers/elastic/. - The actual indexer is the gitlab-elasticsearch-indexer Go binary (version pinned in
GITLAB_ELASTICSEARCH_INDEXER_VERSION). - Reindexing migrations live in
ee/elastic/migrate/.
Zoekt
Zoekt is a Go-based code search engine optimized for repository content. GitLab uses it for code search at scale.
- Index management workers in
ee/app/workers/search/zoekt/. - The indexer binary is gitlab-zoekt-indexer (version pinned in
GITLAB_ZOEKT_VERSION). - Per-namespace enablement is tracked in
ee/app/models/search/zoekt/*.
Active Context
A newer abstraction designed for retrieval-augmented generation (RAG) and Duo Chat:
gems/gitlab-active-context/provides a backend-agnostic API.ee/lib/active_context/contains GitLab-specific collectors and queries.- Embeddings are stored in pgvector or in dedicated stores.
Search service entry point
SearchService (app/services/search_service.rb) picks the right strategy:
- Tries Elasticsearch via
Gitlab::SearchResults::Elasticif enabled. - Falls back to Postgres-based
Gitlab::SearchResults. - Code search may delegate to Zoekt.
GraphQL search uses app/graphql/types/projects/searchable_* types, which thread through the same service.
Indexing
Each indexable model declares its mapping. Examples (EE):
ee/app/models/concerns/elastic/application_versioned_search.rb.- Per-model
as_indexed_json.
When a model is created or updated, callbacks enqueue ElasticIndexerWorker (or its specialized variants).
Reindexing migrations
Like database migrations, search has its own migration mechanism (ee/elastic/migrate/) for incompatible mapping changes. Each migration runs on a Sidekiq worker and tracks progress.
Configuration
Admin Area → Settings → Search has:
- Elasticsearch URLs.
- Index limits per namespace.
- Zoekt enablement.
- Active Context backend.
The model ApplicationSetting (app/models/application_setting.rb) stores these.
Related
- Background — search migration history.
- Architecture — where search sits.
Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.