# Go Project Layout Patterns Used by Popular Go Projects: Standard Structure Explained

> Explore Go project layout patterns used by popular projects like Kubernetes. Learn the standard structure for scalable, compiler-enforced architectures with /cmd, /internal, and /pkg.

- Repository: [golang-standards/project-layout](https://github.com/golang-standards/project-layout)
- Tags: best-practices
- Published: 2026-03-06

---

**The Standard Go Project Layout organizes code into `/cmd` for executables, `/internal` for private packages, and `/pkg` for public libraries, a pattern adopted by Kubernetes, Prometheus, and Terraform to maintain scalable, compiler-enforced architectures.**

The `golang-standards/project-layout` repository documents Go project layout patterns observed across the Go ecosystem to help developers structure applications as they grow. While not an official Go language standard, these conventions are implemented in major open-source repositories to separate concerns, enforce privacy boundaries through compiler rules, and create predictable codebases that scale from microservices to cloud-native platforms.

## Core Directory Structure

The layout documented in the repository's [`README.md`](https://github.com/golang-standards/project-layout/blob/main/README.md) organizes projects into logical groups that separate executable entry points from reusable libraries and infrastructure configuration.

### /cmd: Executable Entry Points

The **`/cmd`** directory contains the `main` package entry points for applications built by the project. According to [`cmd/README.md`](https://github.com/golang-standards/project-layout/blob/main/cmd/README.md), this pattern keeps `main` functions minimal—typically just wiring dependency injection and calling into internal packages—while supporting multiple binaries from a single repository.

Major projects using this pattern include **Velero**, **Moby**, **Prometheus**, **InfluxDB**, **Kubernetes**, **Dapr**, and **go-ethereum**. Each subdirectory under `/cmd` represents a specific binary, such as [`/cmd/myapp/main.go`](https://github.com/golang-standards/project-layout/blob/main//cmd/myapp/main.go).

### /internal: Compiler-Enforced Privacy

The **`/internal`** directory stores private application code and library packages that external projects cannot import. As documented in [`internal/README.md`](https://github.com/golang-standards/project-layout/blob/main/internal/README.md), the Go compiler enforces this privacy: any package under an `internal/` path can only be imported by code within the same module subtree.

Projects leveraging this enforcement include **Terraform**, **InfluxDB**, **Perkeep**, **Jaeger**, **Moby**, **Satellity**, and **MinIO**. This prevents accidental API leakage and clarifies which packages constitute the public surface area versus implementation details.

### /pkg: Public Library APIs

The **`/pkg`** directory signals that contained code is safe for external consumption, though its use is optional and debated within the community. As noted in [`pkg/README.md`](https://github.com/golang-standards/project-layout/blob/main/pkg/README.md), some teams place public libraries here while others use top-level directories directly.

Notable adopters include **Containerd**, **Slim**, **Telepresence**, **Jaeger**, **Istio**, **Kaniko**, and **Gvisor**. When present, `/pkg` provides a clear contract: packages here maintain backward compatibility, while code outside it (especially in `/internal`) does not.

### Supporting Infrastructure Directories

Beyond code organization, the standard layout defines directories for non-Go assets and operational concerns:

- **`/api`** – API protocol definitions (OpenAPI/Swagger, Protocol Buffers)
- **`/web`** – Static web assets and frontend templates
- **`/configs`** – Default configuration templates and schema files
- **`/deployments`** – Kubernetes manifests, Helm charts, and orchestration configs
- **`/scripts`** – Build and installation helper scripts (documented in [`scripts/README.md`](https://github.com/golang-standards/project-layout/blob/main/scripts/README.md))
- **`/build`** – CI/CD configurations and packaging scripts (documented in [`build/README.md`](https://github.com/golang-standards/project-layout/blob/main/build/README.md))
- **`/tools`** – Helper programs and development utilities
- **`/examples`** – Sample applications demonstrating API usage
- **`/vendor`** – Vendored third-party dependencies for reproducible builds

## Real-World Implementation Example

A typical project following these Go project layout patterns structures code to maximize reusability while enforcing boundaries. The following examples demonstrate the relationship between `/cmd`, `/internal`, and `/pkg`.

### Minimal Main Package

In [`/cmd/myapp/main.go`](https://github.com/golang-standards/project-layout/blob/main//cmd/myapp/main.go), the entry point remains minimal, delegating to internal packages:

```go
package main

import (
    "log"

    "github.com/yourorg/yourproj/internal/app"
)

func main() {
    if err := app.Run(); err != nil {
        log.Fatalf("application error: %v", err)
    }
}

```

This pattern ensures the `main` function only handles process lifecycle concerns, while business logic resides in importable packages.

### Private Application Logic

The [`/internal/app/app.go`](https://github.com/golang-standards/project-layout/blob/main//internal/app/app.go) file contains implementation details that cannot be imported by external modules:

```go
package app

import (
    "fmt"
    "github.com/yourorg/yourproj/internal/pkg/util"
)

func Run() error {
    fmt.Println("starting app")
    return util.DoWork()
}

```

Because this lives under `/internal`, the Go compiler prevents other repositories from importing `github.com/yourorg/yourproj/internal/app`.

### Public Utility Libraries

Reusable code intended for external consumers resides in [`/pkg/util/util.go`](https://github.com/golang-standards/project-layout/blob/main//pkg/util/util.go):

```go
package util

import "fmt"

func DoWork() error {
    fmt.Println("doing work in a public package")
    return nil
}

```

External projects can safely import `github.com/yourorg/yourproj/pkg/util`, distinguishing public APIs from private implementation details.

### Configuration Templates

Default configurations are stored in [`/configs/config.yaml`](https://github.com/golang-standards/project-layout/blob/main//configs/config.yaml) for discovery at runtime:

```yaml
port: 8080
log_level: info

```

This separation allows operators to mount configuration without modifying compiled binaries.

## Module Configuration

The repository includes a minimal `go.mod` file demonstrating that these layout patterns work seamlessly with Go modules. The structure supports both library and application development without requiring special build tags or complex `replace` directives, making it compatible with standard `go build` and `go install` workflows.

## Summary

- **The `/cmd` directory** houses executable entry points with minimal `main` functions, adopted by Kubernetes and Prometheus to separate binary concerns from library code.
- **The `/internal` directory** provides compiler-enforced privacy for implementation details, preventing external import and used by Terraform and Jaeger.
- **The `/pkg` directory** optionally exposes stable public APIs for external consumption, implemented by Containerd and Istio.
- **Supporting directories** like `/configs`, `/deployments`, and `/scripts` organize operational assets separately from source code.
- This layout is not an official Go standard but represents consensus patterns from high-scale open-source projects.

## Frequently Asked Questions

### Is the Standard Go Project Layout an official Go standard?

No, the Standard Go Project Layout documented in `golang-standards/project-layout` is not an official Go language specification. It is a community-curated collection of patterns observed in successful open-source projects. The Go team does not mandate any specific directory structure beyond what the `go` tool requires for modules.

### What is the difference between /internal and /pkg in Go projects?

The **`/internal`** directory uses Go's compiler-level enforcement to prevent external packages from importing its contents, making it ideal for application-specific logic you want to keep private. The **`/pkg`** directory, by convention, signals that packages are intended for public use and should maintain backward compatibility, though its use is optional and some projects place public code at the root instead.

### Which popular Go projects use the /cmd directory pattern?

Major infrastructure projects using the `/cmd` pattern include **Kubernetes**, **Prometheus**, **InfluxDB**, **Velero**, **Moby** (Docker), **Dapr**, and **go-ethereum**. These repositories place individual binary entry points in subdirectories like `/cmd/kubelet` or `/cmd/server`, keeping `main` packages isolated and small.

### Should I use /pkg in my Go project?

Using **`/pkg`** depends on your project's scope. If you are building a library intended for external consumption, `/pkg` clearly signals stable public APIs, as seen in **Containerd** and **Istio**. However, for internal applications or when the entire repository is private, omitting `/pkg` and placing packages at the root may reduce unnecessary nesting. The [`pkg/README.md`](https://github.com/golang-standards/project-layout/blob/main/pkg/README.md) notes this convention is controversial and not universally accepted.