How qeesung/gitaly works
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: praefect/server.go Praefect server · service Repo services · server/server.go Gitaly server · proto RPC contract
Components 19
Clients
External callers and front-door transport paths
- GitLab clients · Rails, Workhorse, and gitlab-shell initiate repository actions
- Gitaly nodes · One or more Gitaly servers serving repository data
Gitaly
Main repository service and Git execution stack
- Gitaly server · Server bootstrap and RPC dispatch for repository operations
internal/gitaly/server/server.go - Repo services · Domain services for repository, commit, ref, diff, blob, object pool, hook, and operations RPCs
internal/gitaly/service - Git engine · Native git command execution, pkt-line, packfiles, revisions, refs, and quarantine handling
internal/git - Storage layer · Repository paths, metadata, snapshots, locks, transactions, and WAL coordination
internal/gitaly/storage - Repo utils · Repository lifecycle helpers, custom hooks, locking, create/remove support
internal/gitaly/repoutil - Hook runtime · Custom hooks, pre-receive/post-receive/proc-receive, and ref update orchestration
internal/gitaly/hook - Maintenance · Optimization, commit-graph, pruning, and cleanup workflows
internal/git/housekeeping - Smart HTTP · HTTP upload-pack and receive-pack handling
internal/gitaly/service/smarthttp/server.go - SSH service · 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 · Server bootstrap and cluster-aware request entrypoint
internal/praefect/server.go - Router · Selects the serving Gitaly node for a repository
internal/praefect/router.go - Replicator · Coordinates replication and repair across Gitaly replicas
internal/praefect/replicator.go - Reconciler · Compares replica state and resolves divergence
internal/praefect/reconciler/reconciler.go - Node mgmt · Health, election, tracking, and per-repository node selection
internal/praefect/nodes/manager.go - State store · Repository assignment, queue, and cluster metadata persistence
internal/praefect/datastore/postgres.go
Shared infra
Cross-cutting transport, auth, logging, tracing, and metrics
- RPC contract · Protobuf service definitions and generated Go stubs
proto - Infra stack · Transport middleware, auth, logging, tracing, metrics, and structured errors
internal/grpc
Connections 25
- 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