# Go Project Structure for Microservices Architecture: The Complete golang-standards/project-layout Guide

> Master Go project structure for microservices with golang-standards/project-layout. Learn to organize cmd, internal, pkg, and deployments for maintainable Go applications. Enhance your architecture today.

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

---

**The golang-standards/project-layout repository provides a battle-tested directory structure that separates concerns between service entry points (`/cmd`), private implementation details (`/internal`), shared libraries (`/pkg`), and deployment artifacts (`/deployments`) to build maintainable Go microservices.**

A well-organized repository makes it easier to develop, test, and deploy microservices written in Go. The **golang-standards/project-layout** standard offers a generic, community-vetted directory scheme that enforces import boundaries and supports operational needs such as configuration management and containerization. This guide explains how to adapt this layout specifically for microservice architectures, with practical examples from the source code.

## Why Directory Structure Matters for Go Microservices

Microservice architectures require strict boundaries between services while enabling code reuse for common concerns like logging and metrics. The project-layout standard addresses this by leveraging Go’s **compiler-enforced visibility rules**—particularly the `internal/` directory—to prevent unauthorized cross-service imports. By keeping infrastructure-as-code next to the service source in `deployments/`, the layout also reduces drift between application and operational configurations.

According to the repository’s README, the structure is deliberately generic: you adopt only the directories you need while preserving the same import rules and conventions【/cache/repos/github.com/golang-standards/project-layout/master/README.md#L57-L84】.

## Core Directories for Microservice Architecture

### /cmd: Service Entry Points

The `cmd/` directory holds the entry-point binaries for each microservice. Each service gets its own subdirectory (e.g., `cmd/user-service/`), keeping the `main` package tiny and focused.

This separation ensures that business logic lives in importable packages rather than being trapped in executable code. As noted in [`cmd/README.md`](https://github.com/golang-standards/project-layout/blob/main/cmd/README.md), real-world projects like Kubernetes and Docker use this pattern to manage multiple binaries from a single repository.

```go
// cmd/user-service/main.go
package main

import (
	"log"
	"net/http"

	"github.com/yourorg/yourrepo/internal/app/user"
	"github.com/yourorg/yourrepo/internal/config"
)

func main() {
	// Load configuration (from configs/ folder, env vars, etc.)
	if err := config.Load(); err != nil {
		log.Fatalf("config error: %v", err)
	}

	// Initialise the user service (business logic lives in internal/app/user)
	svc := user.NewService()

	// Register HTTP handlers (could be generated from /api spec)
	http.HandleFunc("/users", svc.HandleUsers)

	// Start HTTP server
	log.Println("User service listening on :8080")
	log.Fatal(http.ListenAndServe(":8080", nil))
}

```

### /internal: Encapsulated Business Logic

The `internal/` directory contains private implementation details—models, repository interfaces, and internal utilities—that **must not** be imported by other services. The Go compiler blocks imports from outside the module, guaranteeing encapsulation at the language level.

Store your service-specific domain logic here to prevent tight coupling between microservices. The [`internal/README.md`](https://github.com/golang-standards/project-layout/blob/main/internal/README.md) explains that any package under this tree is automatically protected by the compiler, making it the safest place for proprietary business rules.

```go
// internal/app/user/service.go
package user

import (
	"encoding/json"
	"net/http"
)

type Service struct{ /* fields like DB, logger */ }

func NewService() *Service { return &Service{} }

func (s *Service) HandleUsers(w http.ResponseWriter, r *http.Request) {
	// Business logic, e.g., fetch users from DB
	users := []string{"alice", "bob"}
	_ = json.NewEncoder(w).Encode(users)
}

```

### /pkg: Reusable Public Libraries

The `pkg/` directory hosts reusable libraries (e.g., `pkg/logger`, `pkg/metrics`) that other services **can** depend on. Unlike `internal/`, code here signals an intentional public API with versioning and documentation expectations.

When building a microservice ecosystem, place cross-cutting concerns like structured logging or distributed tracing here so sibling services can import them via standard module paths like `github.com/yourorg/yourrepo/pkg/logger`.

```go
// pkg/logger/logger.go
package logger

import "log"

func Init() {
	log.SetFlags(log.LstdFlags | log.Lshortfile)
}

```

### /api: Contract-First API Definitions

The `api/` directory stores OpenAPI/Swagger specs, protobuf definitions, or any contract files that describe the service’s external interface. As documented in the **Service Application Directories** section【/cache/repos/github.com/golang-standards/project-layout/master/README.md#L99-L106】, this enables contract-first development and automatic client generation.

```yaml

# api/user-service/openapi.yaml

openapi: "3.0.0"
info:
  title: User Service API
  version: "1.0"
paths:
  /users:
    get:
      summary: List users
      responses:
        '200':
          description: A JSON array of usernames
          content:
            application/json:
              schema:
                type: array
                items:
                  type: string

```

### /configs and /deployments: Operational Configuration

The `configs/` directory houses default configuration files and templating for tools like `consul-template` or `viper`, centralizing config management across environments (dev, staging, prod).

The `deployments/` directory contains Kubernetes manifests, Helm charts, Dockerfiles, and Terraform modules. Keeping infrastructure as code next to the service it deploys reduces configuration drift and simplifies CI/CD pipelines.

```dockerfile

# deployments/Dockerfile

FROM golang:1.22-alpine AS builder
WORKDIR /app
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN go build -o /bin/user-service ./cmd/user-service

FROM alpine:latest
COPY --from=builder /bin/user-service /usr/local/bin/user-service
ENTRYPOINT ["user-service"]

```

## Optional Supporting Directories

While a typical microservice requires at least `cmd/`, `internal/`, `pkg/`, `api/`, `configs/`, and `deployments/`, the layout includes additional directories for specific needs:

- **`/web`**: Static assets, HTML templates, or SPA bundles if the microservice also serves a UI. Isolates web concerns from pure Go logic.
- **`/scripts`**: Build, lint, CI helpers, and custom automation scripts that encourage reproducible builds.
- **`/build`**: CI/CD pipelines, packaging scripts, and container build definitions that separate build logic from source.
- **`/test`**: Integration-test helpers, test data, and example clients that provide a sandbox for end-to-end verification.
- **`/docs`**: Design documents, architecture diagrams, and API documentation for improved onboarding.
- **`/tools`**: Helper binaries that may depend on internal packages (e.g., code generators), keeping auxiliary tooling versioned with the service.

## Key Reference Files in the Repository

When implementing this Go project structure for microservices architecture, consult these specific files in the `golang-standards/project-layout` repository:

- **[`README.md`](https://github.com/golang-standards/project-layout/blob/main/README.md)**: High-level overview of the layout and rationale for all directories.
- **[`cmd/README.md`](https://github.com/golang-standards/project-layout/blob/main/cmd/README.md)**: Guidelines for the `cmd` directory and examples from real-world projects.
- **[`internal/README.md`](https://github.com/golang-standards/project-layout/blob/main/internal/README.md)**: Explanation of the `internal` import enforcement and recommended sub-structures.
- **[`pkg/README.md`](https://github.com/golang-standards/project-layout/blob/main/pkg/README.md)**: Advice on when to expose code as a public package versus keeping it internal.
- **[`api/README.md`](https://github.com/golang-standards/project-layout/blob/main/api/README.md)**: Guidance on storing API contracts (OpenAPI, protobuf, etc.) and versioning strategies.
- **[`deployments/README.md`](https://github.com/golang-standards/project-layout/blob/main/deployments/README.md)**: Examples of deployment manifests and CI/CD integration patterns.

## Summary

The golang-standards/project-layout provides a proven foundation for Go microservices:

- **`/cmd`** keeps service entry points minimal and focused
- **`/internal`** enforces encapsulation via compiler-level import restrictions
- **`/pkg`** exposes versioned, reusable libraries to other services
- **`/api`** enables contract-first development with OpenAPI and protobuf definitions
- **`/configs`** and **`/deployments`** co-locate operational code with application logic

Adopt directories selectively, evolve the structure as your system grows, and maintain strict boundaries between services to build scalable, maintainable microservice architectures.

## Frequently Asked Questions

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

The **`/internal`** directory contains code that the Go compiler prevents from being imported by other modules, making it ideal for proprietary business logic that should not leak between microservices. The **`/pkg`** directory contains intentionally public code that other services and external projects can import as libraries. Use `internal/` for service-specific implementation details and `pkg/` for cross-cutting concerns like logging or middleware.

### How does the golang-standards/project-layout handle multiple microservices in one repository?

Place each microservice’s entry point in its own subdirectory under **`/cmd`** (e.g., `cmd/user-service/`, `cmd/order-service/`). This pattern, used by large projects like Kubernetes, allows a monorepo structure where services share common libraries in `/pkg` while maintaining private business logic in `/internal`. Each subdirectory under `cmd/` represents a separate binary with its own `main` package.

### Where should I put Docker and Kubernetes configurations for Go microservices?

Store container definitions in **`/deployments`**, which is specifically designed for Kubernetes manifests, Helm charts, Dockerfiles, and Terraform modules. The [`deployments/README.md`](https://github.com/golang-standards/project-layout/blob/main/deployments/README.md) file in the repository provides examples of keeping infrastructure-as-code next to the service it deploys. This co-location reduces drift and simplifies CI/CD pipelines by ensuring build artifacts and deployment configurations version together.

### Can I use only parts of the golang-standards/project-layout for my microservice?

Yes. The layout is deliberately generic, and the repository’s documentation explicitly recommends adopting only the directories you need. A minimal microservice might only require `cmd/`, `internal/`, `pkg/`, and `api/`, while adding `deployments/` and `configs/` as operational requirements grow. The critical requirement is maintaining the import boundary rules: keep private code in `internal/` and public libraries in `pkg/`.