# Recommended Project Structure and Layout for a Kratos Microservice

> Discover the recommended Kratos microservice project structure. Utilize kratos new for a layered layout with distinct biz data and service directories, optimizing your development with go-kratos.

- Repository: [Kratos/kratos](https://github.com/go-kratos/kratos)
- Tags: best-practices
- Published: 2026-03-02

---

**Use the `kratos new` CLI command to scaffold a layered directory structure that isolates business logic in `internal/biz`, data access in `internal/data`, and transport concerns in `internal/service`, based on the official `kratos-layout` template.**

The `go-kratos/kratos` framework enforces an opinionated **Kratos microservice project structure** that promotes clean architecture and testability. When you run the project generator, it clones the `kratos-layout` repository and creates a standard directory hierarchy that separates concerns across distinct layers. This layout ensures that domain logic remains independent of infrastructure and transport protocols.

## Standard Directory Layout

Running `kratos new <service>` produces the following top-level structure:

```

<service>/
├── cmd/
│   └── <service>/          # Application entry point (main.go)

├── internal/
│   ├── biz/                # Business use-cases and domain logic

│   ├── data/               # Data access layer (repositories, DB clients)

│   ├── service/            # gRPC and HTTP transport handlers

│   └── server/             # Wire dependency injection and server wiring

├── configs/                # YAML/JSON configuration files

├── deployments/            # Docker Compose, Kubernetes manifests

├── pkg/                    # Optional reusable library code

├── go.mod                  # Go module definition

└── README.md

```

The `cmd/<service>/` directory contains the executable entry point, while `internal/` houses the core application layers that implement the hexagonal architecture pattern.

## Layer Responsibilities and Design Philosophy

Each directory in the **Kratos project structure** serves a specific architectural purpose:

| Layer | Directory | Purpose | Typical Contents |
|-------|-----------|---------|------------------|
| **Entry Point** | `cmd/<service>/` | Application bootstrap and server lifecycle management | [`main.go`](https://github.com/go-kratos/kratos/blob/main/main.go) that initializes configuration and calls `server.NewApp` |
| **Business Logic** | `internal/biz/` | Domain use-cases and business rules independent of transport or storage | Use-case structs, domain interfaces, and entity validation logic |
| **Data Access** | `internal/data/` | Persistence adapters and external service clients | Repository implementations, GORM models, Redis wrappers, third-party API clients |
| **Transport** | `internal/service/` | Protocol handlers that convert requests/responses to business calls | Generated protobuf service implementations, HTTP handlers, request DTOs |
| **Wiring** | `internal/server/` | Dependency injection configuration using Google Wire | [`wire.go`](https://github.com/go-kratos/kratos/blob/main/wire.go) provider sets that compose the application graph |

This separation ensures that changes to database schema (in `data`) or communication protocols (in `service`) do not leak into the core business logic (in `biz`).

## CLI Implementation Details

The project scaffolding logic resides in the Kratos CLI source code at `cmd/kratos/internal/project/`.

The template URL is defined in [`project.go`](https://github.com/go-kratos/kratos/blob/main/project.go) at line 20, which maps the service template to the `kratos-layout` GitHub repository. When executing `kratos new`, the tool clones this template and performs automated renaming operations. Specifically, in [`new.go`](https://github.com/go-kratos/kratos/blob/main/new.go) lines 45-48, the generator renames the default `cmd/server` directory to match your provided service name, ensuring import paths align correctly.

The validity of this structure is verified in [`project_test.go`](https://github.com/go-kratos/kratos/blob/main/project_test.go) at line 40, which asserts that generated projects correctly import `internal/biz`, confirming the business layer is properly wired into the module.

## Anatomy of the Generated Code

### Entry Point (`cmd/<service>/main.go`)

The generated [`main.go`](https://github.com/go-kratos/kratos/blob/main/main.go) bootstraps the Kratos application by loading configuration and invoking the Wire-generated `NewApp` function:

```go
package main

import (
	"flag"

	"github.com/go-kratos/kratos/v2"
	"github.com/go-kratos/kratos/v2/config"
	"github.com/go-kratos/kratos/v2/log"
	"helloworld/internal/server"
)

func main() {
	var (
		cfgPath = flag.String("conf", "./configs", "config path")
	)
	flag.Parse()

	// Load configuration from YAML/JSON files
	c, err := config.New(
		config.WithSource(
			file.NewSource(*cfgPath),
		),
	)
	if err != nil {
		panic(err)
	}
	if err = c.Load(); err != nil {
		panic(err)
	}

	// Build the application via Wire injection
	app, cleanup, err := server.NewApp(c)
	if err != nil {
		panic(err)
	}
	defer cleanup()

	// Run the server
	if err = app.Run(); err != nil {
		log.Fatalf("server exited with error: %v", err)
	}
}

```

This file is created automatically during the copy step in [`new.go`](https://github.com/go-kratos/kratos/blob/main/new.go) at line 42.

### Business Logic (`internal/biz/`)

The `biz` layer defines use-case interfaces and implementations that operate on domain entities. It declares repository interfaces that the `data` layer will implement:

```go
package biz

type Greeter interface {
	SayHello(name string) (*HelloReply, error)
}

type GreeterRepo interface {
	SaveGreeting(greeting string) error
}

type greeterUseCase struct {
	repo GreeterRepo
}

func NewGreeterUseCase(repo GreeterRepo) Greeter {
	return &greeterUseCase{repo: repo}
}

func (g *greeterUseCase) SayHello(name string) (*HelloReply, error) {
	// Pure domain logic without transport or storage concerns
	return &HelloReply{Message: "Hello " + name}, nil
}

```

### Data Layer (`internal/data/`)

The `data` package implements repository interfaces declared in `biz`. It contains concrete database models, ORM configurations, and cache clients:

```go
package data

type greeterRepo struct {
	db *gorm.DB
}

func NewGreeterRepo(db *gorm.DB) biz.GreeterRepo {
	return &greeterRepo{db: db}
}

func (r *greeterRepo) SaveGreeting(greeting string) error {
	// Persistence logic using GORM or SQL drivers
	return nil
}

```

### Transport Layer (`internal/service/`)

The `service` package implements generated protobuf service interfaces, translating gRPC or HTTP requests into business method calls:

```go
package service

import (
	"context"
	pb "helloworld/api/helloworld/v1"
	"helloworld/internal/biz"
)

type GreeterService struct {
	biz.Greeter
}

func (s *GreeterService) SayHello(ctx context.Context, req *pb.HelloRequest) (*pb.HelloReply, error) {
	reply, err := s.Greeter.SayHello(req.Name)
	if err != nil {
		return nil, err
	}
	return &pb.HelloReply{Message: reply.Message}, nil
}

```

### Dependency Wiring ([`internal/server/wire.go`](https://github.com/go-kratos/kratos/blob/main/internal/server/wire.go))

The `server` package uses Google Wire to compose the application graph. The [`wire.go`](https://github.com/go-kratos/kratos/blob/main/wire.go) file declares provider sets that connect the layers:

```go
//go:build wireinject
// +build wireinject

package server

import (
	"github.com/go-kratos/kratos/v2"
	"github.com/google/wire"
	"helloworld/internal/biz"
	"helloworld/internal/data"
	"helloworld/internal/service"
)

func NewApp(conf config.Config) (*kratos.App, func(), error) {
	panic(wire.Build(
		// Provider sets for each layer
		biz.NewGreeterUseCase,
		data.NewGreeterRepo,
		service.NewGreeterService,
		
		// Server configuration
		NewServer,
	))
}

```

Running `wire` in this directory generates the concrete initialization code that satisfies all interface dependencies.

## Summary

- The **Kratos microservice project structure** is generated by the `kratos new` command, which clones the official `kratos-layout` template.
- The layout enforces strict separation between **entry point** (`cmd/`), **business logic** (`internal/biz/`), **data access** (`internal/data/`), and **transport** (`internal/service/`).
- **Dependency injection** is centralized in [`internal/server/wire.go`](https://github.com/go-kratos/kratos/blob/main/internal/server/wire.go), using Google Wire to compose layers without manual singleton management.
- Configuration files belong in `configs/`, while deployment artifacts reside in `deployments/`.
- The CLI automates directory renaming and import path validation, ensuring the generated module is immediately runnable.

## Frequently Asked Questions

### What command creates the recommended Kratos project structure?

Run `kratos new <service-name>` from your terminal. This command clones the `kratos-layout` template repository and renames the default `cmd/server` directory to `cmd/<service-name>` according to the logic in [`cmd/kratos/internal/project/new.go`](https://github.com/go-kratos/kratos/blob/main/cmd/kratos/internal/project/new.go) lines 45-48, producing a ready-to-use module.

### Why does Kratos separate business logic into `internal/biz` rather than placing it in the service handlers?

Isolating domain use-cases in `internal/biz` ensures that business rules remain independent of transport protocols (gRPC/HTTP) and storage technologies. This allows you to test core logic without spinning up servers or databases, and to swap infrastructure implementations without modifying domain code.

### Where should database models and third-party API clients reside?

Place concrete implementations in `internal/data/`. This package implements repository interfaces defined in `internal/biz/`, housing GORM models, SQL queries, Redis clients, and external API wrappers. Keep domain entities in `internal/biz/` while persistence details remain encapsulated in `internal/data/`.

### Can I customize the generated project structure or remove the Wire dependency?

While you can manually modify the directory layout after generation, deviating from the standard structure may break assumptions in the Kratos ecosystem and complicate future updates. Wire is optional but recommended; removing it requires manual dependency injection in `internal/server/`, as the `NewApp` function expects pre-wired dependencies to build the `kratos.App` instance.