# qeesung/gitaly architecture

> Architecture diagram of the GitHub repository qeesung/gitaly, generated by GitDiagram from its file tree, README and a sample of source files (last updated 2026-05-13). It is an AI-made overview: check details against the source.

- Interactive diagram: https://gitdiagram.com/qeesung/gitaly
- Repository: https://github.com/qeesung/gitaly

## Overview

1. **Overall shape**
   Gitaly is a Go-based Git RPC service. Its core responsibility is to translate GitLab requests into local Git operations on repository filesystems, rather than storing Git data itself.

2. **Primary runtime processes**
   The repo builds multiple executables with distinct roles: `gitaly` is the main repository service, `praefect` is the HA/replication coordinator, and helper binaries such as `gitaly-ssh`, `gitaly-hooks`, `gitaly-backup`, `gitaly-debug`, and `gitaly-lfs-smudge` cover transport, hooks, backup, diagnostics, and LFS-related workflows.

3. **Client-facing boundaries**
   External callers are GitLab components: Rails, Workhorse, and gitlab-shell talk to Gitaly over gRPC/RPC. SSH and HTTP Git traffic are handled by specialized service paths in the repo, but they ultimately route back into the same Git execution and repository logic.

4. **API contract and service partitioning**
   The `proto/` directory defines the RPC surface. Generated Go stubs under `proto/go/gitalypb/` are used by service implementations under `internal/gitaly/service/*` and `internal/praefect/service/*`. This is the main contract boundary between clients and server logic.

5. **Gitaly server core**
   The main server lives under `internal/gitaly/` and `internal/gitaly/service/`. It exposes Git operations grouped by domain: repository management, commits, refs, diffs, blobs, object pools, hooks, smart HTTP, SSH, cleanup, operations, conflicts, and analysis. Each service is a separate boundary around a family of RPCs.

6. **Git execution model**
   Gitaly’s internal Git layer (`internal/git/`) wraps native `git` commands, packfiles, pkt-line streams, object lookup, revisions, refs, quarantine handling, and repository metadata. The service layer depends on this package to perform the actual Git work on disk.

7. **Repository and storage model**
   Repository data is filesystem-backed. Supporting packages in `internal/gitaly/storage/`, `internal/gitaly/repoutil/`, `internal/git/localrepo/`, and `internal/git/objectpool/` manage repository paths, alternates, object pools, snapshots, locking, and metadata. This is the main persistence boundary: Git data lives on local storage, not in a database.

8. **Background maintenance and integrity**
   Several packages handle housekeeping and optimization, such as commit-graph maintenance, object pruning, repository optimization, and cleanup of stale data. These are internal workflows that operate on repositories independently of request/response RPCs.

9. **High availability via Praefect**
   Praefect is the HA layer between clients and Gitaly nodes. It routes requests, tracks repository assignment and replication state, and coordinates consistency across replicas. Its state is persisted in PostgreSQL through the `internal/praefect/datastore/` layer and updated by reconciliation/replication components.

10. **Praefect subsystems**
   Praefect is split into router, node management, replicator, reconciler, verifier, transaction handling, repository cleanup, and health-checking concerns. These packages form the control plane for deciding which Gitaly node serves a repository and how data is replicated or repaired.

11. **Transactional and metadata coordination**
   Both Gitaly and Praefect have transaction-related subsystems. Gitaly’s storage manager and WAL/snapshot packages coordinate repository changes, while Praefect’s transaction manager and voting logic coordinate multi-node repository operations and cluster metadata changes.

12. **Transport, middleware, and observability**
   gRPC is the primary network transport. Shared infrastructure under `internal/grpc/`, `internal/log/`, `internal/tracing/`, `internal/prometheus/`, and `internal/structerr/` provides middleware, auth, request metadata, rate/concurrency limiting, tracing, metrics, and structured error mapping. These are cross-cutting layers around the services.

13. **Auth and security boundaries**
   Authentication helpers exist in `auth/`, `internal/gitaly/server/auth/`, and `internal/grpc/middleware/`. The repo also contains signature verification, GPG/SSH signing, quarantine handling, and custom hook support, which are important because many Git actions need controlled execution and content validation.

14. **Operational tooling and environments**
   The repository includes extensive support for benchmark/demo cluster creation, Terraform/Ansible provisioning, CI config, and test helpers. These are not part of the runtime architecture, but they show that deployment is expected across single-node Gitaly, Praefect-backed clusters, and local test harnesses.

15. **What to draw in an architecture diagram**
   The main diagram should show GitLab clients calling either Gitaly directly or Praefect first; Gitaly then shells out to `git` and reads/writes repository files on local storage. For HA, Praefect sits in front of multiple Gitaly nodes and uses PostgreSQL for cluster state, routing, and replication coordination.

Main entry points: [`internal/praefect/server.go`](https://github.com/qeesung/gitaly/blob/master/internal/praefect/server.go) (Praefect server), [`internal/gitaly/service`](https://github.com/qeesung/gitaly/tree/master/internal/gitaly/service) (Repo services), [`internal/gitaly/server/server.go`](https://github.com/qeesung/gitaly/blob/master/internal/gitaly/server/server.go) (Gitaly server), [`proto`](https://github.com/qeesung/gitaly/tree/master/proto) (RPC contract)

## Diagram (Mermaid)

```mermaid
flowchart TD

subgraph group_clients["Clients"]
  node_gitlab_clients(("GitLab clients<br/>external callers"))
  node_gitaly_nodes(("Gitaly nodes<br/>backend replicas"))
end

subgraph group_gitaly["Gitaly"]
  node_gitaly_server["Gitaly server<br/>main daemon<br/>[server.go]"]
  node_repo_services["Repo services<br/>RPC handlers"]
  node_git_execution["Git engine<br/>git wrapper"]
  node_storage_model[("Storage layer<br/>filesystem storage")]
  node_repo_utils["Repo utils<br/>fs helpers"]
  node_hook_runtime["Hook runtime<br/>hook execution"]
  node_maintenance["Maintenance<br/>housekeeping"]
  node_smart_http["Smart HTTP<br/>git-http path<br/>[server.go]"]
  node_ssh_service["SSH service<br/>git-ssh path<br/>[server.go]"]
end

subgraph group_praefect["Praefect"]
  node_praefect_server["Praefect server<br/>ha daemon<br/>[server.go]"]
  node_praefect_router["Router<br/>request routing<br/>[router.go]"]
  node_praefect_replication["Replicator<br/>replication engine<br/>[replicator.go]"]
  node_praefect_reconcile["Reconciler<br/>consistency repair<br/>[reconciler.go]"]
  node_praefect_nodes["Node mgmt<br/>cluster nodes<br/>[manager.go]"]
  node_praefect_store[("State store<br/>postgres datastore<br/>[postgres.go]")]
end

subgraph group_infra["Shared infra"]
  node_grpc_api["RPC contract<br/>proto surface"]
  node_shared_infra["Infra stack<br/>grpc middleware"]
end

node_gitlab_clients -->|"call"| node_grpc_api
node_grpc_api -->|"serve"| node_gitaly_server
node_grpc_api -->|"serve"| node_praefect_server
node_shared_infra -->|"wraps"| node_gitaly_server
node_shared_infra -->|"wraps"| node_praefect_server
node_gitaly_server -->|"dispatches"| node_repo_services
node_repo_services -->|"executes"| node_git_execution
node_repo_services -->|"reads/writes"| node_storage_model
node_repo_services -->|"invokes"| node_hook_runtime
node_repo_services -->|"triggers"| node_maintenance
node_repo_services -->|"handles"| node_smart_http
node_repo_services -->|"handles"| node_ssh_service
node_storage_model -->|"supports"| node_repo_utils
node_repo_utils -->|"prepares"| node_git_execution
node_praefect_server -->|"uses"| node_praefect_router
node_praefect_server -->|"uses"| node_praefect_replication
node_praefect_server -->|"uses"| node_praefect_reconcile
node_praefect_server -->|"uses"| node_praefect_nodes
node_praefect_server -->|"persists"| node_praefect_store
node_praefect_router -->|"routes to"| node_gitaly_nodes
node_praefect_replication -->|"replicates"| node_gitaly_nodes
node_praefect_reconcile -->|"reads state"| node_praefect_store
node_praefect_nodes -->|"tracks"| node_praefect_store
node_gitlab_clients -->|"via HA"| node_praefect_server
node_praefect_server -->|"proxies"| node_gitaly_server

click node_grpc_api "https://github.com/qeesung/gitaly/tree/master/proto"
click node_shared_infra "https://github.com/qeesung/gitaly/tree/master/internal/grpc"
click node_gitaly_server "https://github.com/qeesung/gitaly/blob/master/internal/gitaly/server/server.go"
click node_repo_services "https://github.com/qeesung/gitaly/tree/master/internal/gitaly/service"
click node_git_execution "https://github.com/qeesung/gitaly/tree/master/internal/git"
click node_storage_model "https://github.com/qeesung/gitaly/tree/master/internal/gitaly/storage"
click node_repo_utils "https://github.com/qeesung/gitaly/tree/master/internal/gitaly/repoutil"
click node_hook_runtime "https://github.com/qeesung/gitaly/tree/master/internal/gitaly/hook"
click node_maintenance "https://github.com/qeesung/gitaly/tree/master/internal/git/housekeeping"
click node_smart_http "https://github.com/qeesung/gitaly/blob/master/internal/gitaly/service/smarthttp/server.go"
click node_ssh_service "https://github.com/qeesung/gitaly/blob/master/internal/gitaly/service/ssh/server.go"
click node_praefect_server "https://github.com/qeesung/gitaly/blob/master/internal/praefect/server.go"
click node_praefect_router "https://github.com/qeesung/gitaly/blob/master/internal/praefect/router.go"
click node_praefect_replication "https://github.com/qeesung/gitaly/blob/master/internal/praefect/replicator.go"
click node_praefect_reconcile "https://github.com/qeesung/gitaly/blob/master/internal/praefect/reconciler/reconciler.go"
click node_praefect_nodes "https://github.com/qeesung/gitaly/blob/master/internal/praefect/nodes/manager.go"
click node_praefect_store "https://github.com/qeesung/gitaly/blob/master/internal/praefect/datastore/postgres.go"

classDef toneNeutral fill:#f8fafc,stroke:#334155,stroke-width:1.5px,color:#0f172a
classDef toneBlue fill:#dbeafe,stroke:#2563eb,stroke-width:1.5px,color:#172554
classDef toneAmber fill:#fef3c7,stroke:#d97706,stroke-width:1.5px,color:#78350f
classDef toneMint fill:#dcfce7,stroke:#16a34a,stroke-width:1.5px,color:#14532d
classDef toneRose fill:#ffe4e6,stroke:#e11d48,stroke-width:1.5px,color:#881337
classDef toneIndigo fill:#e0e7ff,stroke:#4f46e5,stroke-width:1.5px,color:#312e81
classDef toneTeal fill:#ccfbf1,stroke:#0f766e,stroke-width:1.5px,color:#134e4a
class node_gitlab_clients,node_gitaly_nodes toneBlue
class node_gitaly_server,node_repo_services,node_git_execution,node_storage_model,node_repo_utils,node_hook_runtime,node_maintenance,node_smart_http,node_ssh_service toneAmber
class node_praefect_server,node_praefect_router,node_praefect_replication,node_praefect_reconcile,node_praefect_nodes,node_praefect_store toneMint
class node_grpc_api,node_shared_infra toneRose
```

## Components

### Clients

External callers and front-door transport paths

- **GitLab clients**: external callers · Rails, Workhorse, and gitlab-shell initiate repository actions
- **Gitaly nodes**: backend replicas · One or more Gitaly servers serving repository data

### Gitaly

Main repository service and Git execution stack

- [Gitaly server](https://github.com/qeesung/gitaly/blob/master/internal/gitaly/server/server.go): main daemon · Server bootstrap and RPC dispatch for repository operations · `internal/gitaly/server/server.go`
- [Repo services](https://github.com/qeesung/gitaly/tree/master/internal/gitaly/service): RPC handlers · Domain services for repository, commit, ref, diff, blob, object pool, hook, and operations RPCs · `internal/gitaly/service`
- [Git engine](https://github.com/qeesung/gitaly/tree/master/internal/git): git wrapper · Native git command execution, pkt-line, packfiles, revisions, refs, and quarantine handling · `internal/git`
- [Storage layer](https://github.com/qeesung/gitaly/tree/master/internal/gitaly/storage): filesystem storage · Repository paths, metadata, snapshots, locks, transactions, and WAL coordination · `internal/gitaly/storage`
- [Repo utils](https://github.com/qeesung/gitaly/tree/master/internal/gitaly/repoutil): fs helpers · Repository lifecycle helpers, custom hooks, locking, create/remove support · `internal/gitaly/repoutil`
- [Hook runtime](https://github.com/qeesung/gitaly/tree/master/internal/gitaly/hook): hook execution · Custom hooks, pre-receive/post-receive/proc-receive, and ref update orchestration · `internal/gitaly/hook`
- [Maintenance](https://github.com/qeesung/gitaly/tree/master/internal/git/housekeeping): housekeeping · Optimization, commit-graph, pruning, and cleanup workflows · `internal/git/housekeeping`
- [Smart HTTP](https://github.com/qeesung/gitaly/blob/master/internal/gitaly/service/smarthttp/server.go): git-http path · HTTP upload-pack and receive-pack handling · `internal/gitaly/service/smarthttp/server.go`
- [SSH service](https://github.com/qeesung/gitaly/blob/master/internal/gitaly/service/ssh/server.go): git-ssh path · SSH upload-pack, upload-archive, and receive-pack handling · `internal/gitaly/service/ssh/server.go`

### Praefect

High-availability routing, replication, and cluster state

- [Praefect server](https://github.com/qeesung/gitaly/blob/master/internal/praefect/server.go): ha daemon · Server bootstrap and cluster-aware request entrypoint · `internal/praefect/server.go`
- [Router](https://github.com/qeesung/gitaly/blob/master/internal/praefect/router.go): request routing · Selects the serving Gitaly node for a repository · `internal/praefect/router.go`
- [Replicator](https://github.com/qeesung/gitaly/blob/master/internal/praefect/replicator.go): replication engine · Coordinates replication and repair across Gitaly replicas · `internal/praefect/replicator.go`
- [Reconciler](https://github.com/qeesung/gitaly/blob/master/internal/praefect/reconciler/reconciler.go): consistency repair · Compares replica state and resolves divergence · `internal/praefect/reconciler/reconciler.go`
- [Node mgmt](https://github.com/qeesung/gitaly/blob/master/internal/praefect/nodes/manager.go): cluster nodes · Health, election, tracking, and per-repository node selection · `internal/praefect/nodes/manager.go`
- [State store](https://github.com/qeesung/gitaly/blob/master/internal/praefect/datastore/postgres.go): postgres datastore · Repository assignment, queue, and cluster metadata persistence · `internal/praefect/datastore/postgres.go`

### Shared infra

Cross-cutting transport, auth, logging, tracing, and metrics

- [RPC contract](https://github.com/qeesung/gitaly/tree/master/proto): proto surface · Protobuf service definitions and generated Go stubs · `proto`
- [Infra stack](https://github.com/qeesung/gitaly/tree/master/internal/grpc): grpc middleware · Transport middleware, auth, logging, tracing, metrics, and structured errors · `internal/grpc`

## Connections

- GitLab clients → RPC contract: call · Clients speak the protobuf RPC contract
- RPC contract → Gitaly server: serve · Generated RPC surface is implemented by the Gitaly daemon
- RPC contract → Praefect server: serve · Praefect exposes its own RPC surface for cluster-aware operations
- Infra stack → Gitaly server: wraps · Middleware and observability surround the Gitaly server
- Infra stack → Praefect server: wraps · Middleware and observability surround the Praefect server
- Gitaly server → Repo services: dispatches · Server routes incoming RPCs to domain services
- Repo services → Git engine: executes · Services perform repository work through the Git execution layer
- Repo services → Storage layer: reads/writes · Services operate on filesystem-backed repository storage
- Repo services → Hook runtime: invokes · Write paths and protected operations run hooks and ref transactions
- Repo services → Maintenance: triggers · Some RPCs trigger repository optimization and cleanup work
- Repo services → Smart HTTP: handles · Dedicated service path for smart HTTP Git traffic
- Repo services → SSH service: handles · Dedicated service path for SSH Git traffic
- Storage layer → Repo utils: supports · Repository utilities manage paths, locks, and lifecycle helpers
- Repo utils → Git engine: prepares · Utilities set up repository state for Git commands
- Praefect server → Router: uses · Server delegates request routing to the router
- Praefect server → Replicator: uses · Server delegates replication coordination to the replicator
- Praefect server → Reconciler: uses · Server delegates consistency repair to the reconciler
- Praefect server → Node mgmt: uses · Server relies on node management and health checking
- Praefect server → State store: persists · Cluster state and assignments are stored in PostgreSQL
- Router → Gitaly nodes: routes to · Routes requests to one of the backend Gitaly replicas
- Replicator → Gitaly nodes: replicates · Replication operations fan out to backend Gitaly nodes
- Reconciler → State store: reads state · Reconciliation uses cluster metadata and queues from the datastore
- Node mgmt → State store: tracks · Node health and assignment state are derived from the datastore
- GitLab clients → Praefect server: via HA · Some clients connect to Praefect before reaching Gitaly
- Praefect server → Gitaly server: proxies · Praefect fronts multiple Gitaly nodes for HA routing
