Temporal — Structure#
Layout pattern#
Custom (non-standard) — Domain-organized monorepo
Temporal does not follow the conventional cmd/internal/pkg Go layout. Instead it uses named top-level namespaces (service/, common/, api/, tools/) that map directly to architectural domains. There is no internal/ directory — the server is explicitly designed to be embeddable via the temporal/ package, so restrictive visibility is avoided. There is also no pkg/ directory; shared code lives in common/. This reflects Temporal’s origins as a fork of Uber’s Cadence, which followed a similar large-scale monorepo structure.
Directory map#
temporal/
├── api/ # Internal Go types mirroring protobuf schemas
│ ├── adminservice/ # Admin gRPC service request/response types
│ ├── historyservice/ # History service internal API types
│ ├── matchingservice/ # Matching service internal API types
│ ├── visibilityservice/ # Visibility service API types
│ ├── *servicemock/ # Generated mocks for each service
│ ├── archiver/ # Archival API types
│ ├── chasm/ # CHASM API types (experimental)
│ ├── persistence/ # Persistence layer API types
│ ├── namespace/ # Namespace management types
│ ├── replication/ # Cross-cluster replication types
│ └── ... # 20+ more domain-specific type packages
├── chasm/ # Coordinated Hierarchical Async State Machine (experimental)
│ └── lib/ # CHASM core library
├── client/ # Internal gRPC client wrappers
│ ├── admin/ # Admin service client
│ ├── frontend/ # Frontend service client
│ ├── history/ # History service client (with sharding)
│ └── matching/ # Matching service client
├── cmd/ # Binary entry points
│ ├── server/ # Primary Temporal server binary
│ └── tools/ # 15+ admin and codegen tools
├── common/ # Shared library (largest directory, ~60 packages)
│ ├── persistence/ # Database abstraction layer (SQL + NoSQL)
│ ├── dynamicconfig/ # Runtime-tunable configuration system
│ ├── metrics/ # Observability (tally/prometheus)
│ ├── membership/ # Gossip-based cluster membership (ringpop, static)
│ ├── authorization/ # Auth plugin interfaces
│ ├── namespace/ # Namespace registry and replication
│ ├── archiver/ # History and visibility archival (S3, GCS, filestore)
│ ├── rpc/ # gRPC server/client setup
│ ├── log/ # Logging abstraction
│ ├── tasks/ # Task processing primitives
│ ├── quotas/ # Rate limiting
│ ├── backoff/ # Retry policies
│ ├── cache/ # In-memory caching
│ ├── collection/ # Generic data structures
│ ├── nexus/ # Nexus RPC integration
│ ├── clock/ # Logical + wall clocks, hybrid logical clock
│ └── ... # 40+ more utility packages
├── components/ # Pluggable workflow engine components
│ ├── callbacks/ # Async callback component
│ ├── nexusoperations/ # Nexus operation component
│ └── dummy/ # Reference component implementation
├── config/ # Static YAML config files
│ └── dynamicconfig/ # Dynamic config value defaults
├── develop/ # Developer environment
│ ├── docker-compose/ # Local dev compose files
│ └── github/ # GitHub Actions helpers
├── docker/ # Docker build files
│ ├── targets/ # server.Dockerfile, admin-tools.Dockerfile
│ └── scripts/ # Container entry scripts
├── docs/ # Architecture and development documentation
│ ├── architecture/ # Design documents
│ ├── admin/ # Operations docs
│ └── development/ # Contributor guides
├── proto/ # Internal protobuf source files
│ └── internal/ # .proto files for internal services
├── schema/ # Database migration schemas
│ ├── cassandra/ # Cassandra schema + versioned migrations
│ ├── mysql/ # MySQL schema (v8)
│ ├── postgresql/ # PostgreSQL schema (v12)
│ ├── sqlite/ # SQLite schema (dev/test)
│ └── elasticsearch/ # ES index mappings
├── service/ # Four production services
│ ├── frontend/ # Public gRPC gateway + REST
│ │ └── configs/ # Frontend-specific rate limit configs
│ ├── history/ # Workflow state machine execution
│ │ ├── api/ # One package per RPC handler (60+ packages)
│ │ ├── shard/ # Shard management
│ │ ├── workflow/ # Workflow execution context
│ │ ├── queues/ # Task queue processing
│ │ ├── replication/ # Cross-cluster replication
│ │ ├── ndc/ # Non-deterministic conflict resolution
│ │ ├── hsm/ # Hierarchical State Machine (new execution model)
│ │ └── tasks/ # Task type definitions
│ ├── matching/ # Task queue routing
│ │ └── workers/ # Matching service background workers
│ └── worker/ # Internal background workflows
│ ├── scanner/ # Workflow/activity scanners
│ ├── scheduler/ # Cron/calendar schedule engine
│ ├── replicator/ # Replication worker
│ ├── batcher/ # Bulk operation batcher
│ └── workerdeployment/ # Worker versioning/deployment
├── temporal/ # Public Go library for embedding the server
│ └── environment/ # Default port/host constants
├── temporaltest/ # Testing utilities for embedded server
│ └── internal/
├── tests/ # Integration and end-to-end tests
│ ├── ndc/ # Non-deterministic conflict (multi-cluster) tests
│ ├── xdc/ # Cross-datacenter replication tests
│ ├── mixedbrain/ # Mixed-version cluster tests
│ └── testcore/ # Shared test infrastructure
└── tools/ # Admin tool implementations
├── cassandra/ # Cassandra schema migration CLI
├── sql/ # SQL schema migration CLI
├── elasticsearch/ # ES index management CLI
├── tdbg/ # Temporal debugger CLI
└── ... # CI, test runner, fairness simulator toolsEntry points#
| Binary | Source | Purpose |
|---|---|---|
temporal-server | cmd/server/main.go | Primary server binary; starts 1-4 services via --service flags |
temporal-cassandra-tool | cmd/tools/cassandra/main.go | Cassandra schema setup and versioned migrations |
temporal-sql-tool | cmd/tools/sql/main.go | MySQL/PostgreSQL/SQLite schema management |
temporal-elasticsearch-tool | cmd/tools/elasticsearch/main.go | Elasticsearch index creation and mapping updates |
tdbg | cmd/tools/tdbg/main.go | Debug CLI for inspecting workflow internals |
| (codegen) | cmd/tools/genrpcwrappers/main.go | Generates gRPC client/server wrapper boilerplate |
| (codegen) | cmd/tools/gendynamicconfig/main.go | Generates typed dynamic config key accessors |
| (codegen) | cmd/tools/genrpcserverinterceptors/main.go | Generates per-method interceptor chains |
| (codegen) | cmd/tools/protoc-gen-go-chasm/main.go | Protoc plugin for CHASM state machine types |
| (codegen) | cmd/tools/gensearchattributehelpers/main.go | Generates search attribute accessor helpers |
| (codegen) | cmd/tools/protogen/main.go | Proto code generation orchestrator |
| (CI) | cmd/tools/ci-notify/main.go | CI notification poster |
| (CI) | cmd/tools/flakereport/main.go | Flaky test report generator |
| (CI) | cmd/tools/test-runner/main.go | Test runner with retry and sharding |
| (CI) | cmd/tools/optimize-test-sharding/main.go | Optimizes test shard allocation |
| (CI) | cmd/tools/fairsim/main.go | Fairness simulator for task queue scheduling |
| (CI) | cmd/tools/parallelize/main.go | Test parallelization helper |
The server binary is the only production artifact. All other binaries are operational or CI tooling.
Package organization#
Internal packages: There is no
internal/directory. Thecommon/package serves as the shared utility namespace, accessible to all. Key internal-facing packages include:common/persistence— Multi-database storage abstraction with plugin backends (cassandra, sql, nosql)common/dynamicconfig— Runtime-tunable settings system (YAML-based, with typed keys)common/membership— Ringpop gossip and static membership providerscommon/authorization— Pluggable auth (JWT, custom claim mappers, audience mappers)common/metrics— Tally-based metrics with service-scoped handlerscommon/archiver— Pluggable history/visibility archival (S3, GCS, filestore)common/namespace— Namespace registry, replication, and change notificationcommon/rpc— gRPC server factory, TLS configuration, interceptor chainscommon/tasks— Generic task processing (sequential, concurrent, interleaved)common/quotas— Rate limiting (token bucket, priority-based)common/nexus— Nexus RPC endpoint and operation handlingservice/history/hsm— Hierarchical State Machine subsystem (new-generation execution model)
Public packages (temporal/): The
temporal/package is the public embedding API:temporal.NewServer(opts...)— Creates a runnable Temporal server instancetemporal.WithConfig,temporal.ForServices,temporal.WithAuthorizer, etc. — Functional optionstemporal/fx.go— Exposes the fx dependency injection graph for programmatic compositiontemporaltest/—TestServertype for embedding Temporal in Go tests without Docker
Layering: The project follows a loose layered architecture:
cmd/ (entry) └── temporal/ (server lifecycle + fx wiring) └── service/{frontend,history,matching,worker}/ (domain services) └── common/ (shared utilities + persistence) └── api/ (internal type definitions)The
api/types serve as the shared data model between layers. Thecomponents/package represents pluggable functional components that hook into the history service without modifying its core.
Build system#
- Build tool: GNU Make (
Makefile), delegating to standardgo build - CGO: Disabled by default (
CGO_ENABLED=0) for portability; SQLite requires CGO if using cgo-sqlite (the project usesmodernc.org/sqlitewhich is pure Go) - Build tags:
disable_grpc_modules(reduces binary size by 16 MB by excluding gRPC client for GCS),test_dep,TEMPORAL_DEBUG - Key targets:
make install/make bins— Build all production binariesmake all— Full CI cycle: clean + proto + bins + check + testmake proto— Compile.protofiles to Go (via buf + protoc)make ci-build-misc— Linting, imports, module tidy, proto breaking change checkmake install-schema-cass-es/install-schema-mysql8/ etc. — Database schema setupmake test— Run unit + integration tests (with race detector, shuffle, 35 min timeout)
- Docker: Yes, multi-stage —
docker/targets/server.Dockerfile(production server) anddocker/targets/admin-tools.Dockerfile(ops tools). Usesdocker-bake.hclfor multi-platform multi-image builds. - Proto pipeline: Source
.protoinproto/internal/→buflinting →protoc→ generated Go types inapi/. The public API proto files come from the externalgo.temporal.io/apimodule.
Notable structural decisions#
service/history/api/— One package per RPC method: The History service has 60+ subdirectories underservice/history/api/, one for each individual RPC handler (e.g.,startworkflow/,respondworkflowtaskcompleted/,updateworkflow/). This extreme single-responsibility decomposition keeps each handler isolated, testable, and independently changeable — a radical departure from the common monolithic handler file pattern.api/vsproto/vs public proto: There are three layers of types: (a) the public-facing proto API in the externalgo.temporal.io/apimodule, (b) internal.protofiles inproto/internal/defining inter-service protocols, and (c) theapi/directory holding generated Go types from (b). This clear separation means the public API and internal protocols can evolve independently.No
internal/— intentional embeddability: The absence ofinternal/is deliberate. Thetemporal/package is a supported public embedding API (the server is used as a library in tests, developer tools, and embedded deployments), so enforcing package-level access restriction would be counterproductive.Rich code generation toolchain: With 7+ dedicated codegen binaries (
genrpcwrappers,gendynamicconfig,genrpcserverinterceptors,gensearchattributehelpers,protoc-gen-go-chasm,protogen,getproto), Temporal treats generated code as a first-class concern. This is unusual in the Go ecosystem and reflects the project’s scale: manual maintenance of gRPC boilerplate, interceptor chains, and typed config keys would be error-prone at this size.components/as extension pattern: Thecomponents/directory introduces a plugin-like model for extending the History service without forking its core. Components (callbacks, nexusoperations) register themselves with the HSM subsystem and are wired via fx at startup. This represents an architectural evolution toward a more modular execution engine.Dual execution models: The coexistence of
service/history/workflow/(the original Cadence-derived state machine) andservice/history/hsm/(the new Hierarchical State Machine) +chasm/(the experimental CHASM layer) reveals active architectural migration. The project is mid-transition between execution model generations.