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 tools

Entry points#

BinarySourcePurpose
temporal-servercmd/server/main.goPrimary server binary; starts 1-4 services via --service flags
temporal-cassandra-toolcmd/tools/cassandra/main.goCassandra schema setup and versioned migrations
temporal-sql-toolcmd/tools/sql/main.goMySQL/PostgreSQL/SQLite schema management
temporal-elasticsearch-toolcmd/tools/elasticsearch/main.goElasticsearch index creation and mapping updates
tdbgcmd/tools/tdbg/main.goDebug CLI for inspecting workflow internals
(codegen)cmd/tools/genrpcwrappers/main.goGenerates gRPC client/server wrapper boilerplate
(codegen)cmd/tools/gendynamicconfig/main.goGenerates typed dynamic config key accessors
(codegen)cmd/tools/genrpcserverinterceptors/main.goGenerates per-method interceptor chains
(codegen)cmd/tools/protoc-gen-go-chasm/main.goProtoc plugin for CHASM state machine types
(codegen)cmd/tools/gensearchattributehelpers/main.goGenerates search attribute accessor helpers
(codegen)cmd/tools/protogen/main.goProto code generation orchestrator
(CI)cmd/tools/ci-notify/main.goCI notification poster
(CI)cmd/tools/flakereport/main.goFlaky test report generator
(CI)cmd/tools/test-runner/main.goTest runner with retry and sharding
(CI)cmd/tools/optimize-test-sharding/main.goOptimizes test shard allocation
(CI)cmd/tools/fairsim/main.goFairness simulator for task queue scheduling
(CI)cmd/tools/parallelize/main.goTest 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. The common/ 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 providers
    • common/authorization — Pluggable auth (JWT, custom claim mappers, audience mappers)
    • common/metrics — Tally-based metrics with service-scoped handlers
    • common/archiver — Pluggable history/visibility archival (S3, GCS, filestore)
    • common/namespace — Namespace registry, replication, and change notification
    • common/rpc — gRPC server factory, TLS configuration, interceptor chains
    • common/tasks — Generic task processing (sequential, concurrent, interleaved)
    • common/quotas — Rate limiting (token bucket, priority-based)
    • common/nexus — Nexus RPC endpoint and operation handling
    • service/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 instance
    • temporal.WithConfig, temporal.ForServices, temporal.WithAuthorizer, etc. — Functional options
    • temporal/fx.go — Exposes the fx dependency injection graph for programmatic composition
    • temporaltest/TestServer type 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. The components/ package represents pluggable functional components that hook into the history service without modifying its core.

Build system#

  • Build tool: GNU Make (Makefile), delegating to standard go build
  • CGO: Disabled by default (CGO_ENABLED=0) for portability; SQLite requires CGO if using cgo-sqlite (the project uses modernc.org/sqlite which 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 binaries
    • make all — Full CI cycle: clean + proto + bins + check + test
    • make proto — Compile .proto files to Go (via buf + protoc)
    • make ci-build-misc — Linting, imports, module tidy, proto breaking change check
    • make install-schema-cass-es / install-schema-mysql8 / etc. — Database schema setup
    • make test — Run unit + integration tests (with race detector, shuffle, 35 min timeout)
  • Docker: Yes, multi-stage — docker/targets/server.Dockerfile (production server) and docker/targets/admin-tools.Dockerfile (ops tools). Uses docker-bake.hcl for multi-platform multi-image builds.
  • Proto pipeline: Source .proto in proto/internal/buf linting → protoc → generated Go types in api/. The public API proto files come from the external go.temporal.io/api module.

Notable structural decisions#

  1. service/history/api/ — One package per RPC method: The History service has 60+ subdirectories under service/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.

  2. api/ vs proto/ vs public proto: There are three layers of types: (a) the public-facing proto API in the external go.temporal.io/api module, (b) internal .proto files in proto/internal/ defining inter-service protocols, and (c) the api/ directory holding generated Go types from (b). This clear separation means the public API and internal protocols can evolve independently.

  3. No internal/ — intentional embeddability: The absence of internal/ is deliberate. The temporal/ 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.

  4. 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.

  5. components/ as extension pattern: The components/ 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.

  6. Dual execution models: The coexistence of service/history/workflow/ (the original Cadence-derived state machine) and service/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.