Oct 23, 20267 min read

Best Go Framework for Microservices in 2026

Go kit, Kratos, gRPC-Go and Connect compared for Go services that call each other and exchange events, plus how Encore adds databases, Pub/Sub and cloud infrastructure to the services you write.

Go is a common language for backend services, and contracts between them are often written in Protocol Buffers, which are designed so that fields can be added or removed without breaking older code.

Go teams often skip frameworks altogether, since net/http is production ready, but a system with a dozen services needs shared answers for contracts between services, how calls are traced, and where each service's database and message broker come from.

What to weigh when choosing:

  • How contracts between services are defined, through Protobuf files or Go types.
  • Whether calls between services are checked at compile time.
  • How much structure the framework imposes, from building blocks to generated project layouts.
  • How each service gets its database, broker and secrets locally and in production.

Go microservice frameworks at a glance

OptionApproachBest fit
gRPC-GoProtobuf contracts with generated clients and serversPolyglot systems that standardize on gRPC
ConnectProtobuf contracts served over HTTP/1.1, HTTP/2 and gRPCTeams that want gRPC contracts that are also easy to call over HTTP
Go kitToolkit of endpoint, transport and middleware abstractionsTeams that want explicit layering without a full framework
KratosFramework with code generation, config and service discoveryTeams that want one opinionated layout for many services
Compare features across all four options
CapabilitygRPC-GoConnectGo kitKratos
ContractProtobufProtobufYour choiceProtobuf
Calls between servicesGenerated clientsGenerated clientsHand-written clientsGenerated clients
Events between servicesBring your own brokerBring your own brokerBring your own brokerBring your own broker
Database per serviceBring your ownBring your ownBring your ownBring your own
TracingThrough interceptorsThrough interceptorsThrough middlewareBuilt in middleware
Local infrastructureYou run itYou run itYou run itYou run it
Production infrastructureYou provision itYou provision itYou provision itYou provision it

gRPC-Go: the standard for RPC

gRPC-Go

gRPC-Go generates servers and clients from Protobuf definitions, with streaming, deadlines and interceptors built into the protocol.

Key features

  • One .proto file defines the contract for every language that calls the service.
  • Unary and streaming RPCs with deadlines and cancellation.
  • Interceptors for auth, logging and tracing.

Good to know

gRPC needs HTTP/2 end to end and is awkward to call from browsers without a proxy, and code generation adds a build step to every contract change.

Try gRPC-Go →

Connect: gRPC contracts over plain HTTP

Connect

Connect uses the same Protobuf definitions but serves them as net/http handlers that speak the Connect protocol, gRPC and gRPC-Web.

Key features

  • Handlers are standard http.Handler values, so existing middleware applies.
  • Endpoints can be called with curl and JSON.
  • Generated clients work in Go and TypeScript.

Good to know

Connect is a transport and contract layer, so service discovery, brokers and databases are still yours to set up.

Try Connect →

Go kit: building blocks

Go kit

Go kit separates each service into endpoints, transports and middleware, so the same business logic can be served over HTTP or gRPC.

Key features

  • Transport-agnostic endpoints with explicit middleware chains.
  • Packages for circuit breaking, rate limiting and metrics.
  • No code generation required.

Good to know

Go kit is verbose by design, and its last tagged release, v0.13.0, shipped in August 2023, so check the repository activity before standardizing on it.

Try Go kit →

Kratos: an opinionated framework

Kratos

Kratos generates service layouts from Protobuf definitions and adds configuration, service registration and middleware.

Key features

  • A CLI that scaffolds services and generates HTTP and gRPC handlers.
  • Pluggable registries for service discovery.
  • Middleware for logging, metrics, tracing and validation.

Good to know

Kratos generates a fixed project layout, so adopting it means following its conventions for configuration, wiring and registries in every service, and brokers and databases are still provisioned by you.

Try Kratos →

Encore: the infrastructure SDK for Go services

Encore

Encore combines Go services with the infrastructure they use through an infrastructure SDK where each service is a package, endpoints are ordinary Go functions marked with an //encore:api comment, and Postgres databases, Pub/Sub topics, cron jobs and secrets are package-level declarations. Calling another service is a function call, and Encore turns it into a network request between the services. encore run starts Postgres locally along with the topics, and a deploy provisions the same resources in your own AWS or GCP account. Whichever option above you pick, Encore can add the databases, topics and secrets to the same services, alongside gRPC-Go, Connect or Kratos for the contracts.

The orders service checks the user, writes the order and publishes an event:

package orders import ( "context" "encore.app/users" "encore.dev/pubsub" "encore.dev/storage/sqldb" ) var db = sqldb.NewDatabase("orders", sqldb.DatabaseConfig{ Migrations: "./migrations", }) type OrderPlaced struct { OrderID int64 UserID int64 } var OrderPlacedTopic = pubsub.NewTopic[*OrderPlaced]("order-placed", pubsub.TopicConfig{ DeliveryGuarantee: pubsub.AtLeastOnce, }) type PlaceOrderParams struct { UserID int64 `json:"user_id"` } type PlaceOrderResponse struct { OrderID int64 `json:"order_id"` } //encore:api public method=POST path=/orders func PlaceOrder(ctx context.Context, p *PlaceOrderParams) (*PlaceOrderResponse, error) { // A call to another service, checked by the compiler. if _, err := users.Get(ctx, p.UserID); err != nil { return nil, err } var id int64 err := db.QueryRow(ctx, "INSERT INTO orders (user_id) VALUES ($1) RETURNING id", p.UserID).Scan(&id) if err != nil { return nil, err } if _, err := OrderPlacedTopic.Publish(ctx, &OrderPlaced{OrderID: id, UserID: p.UserID}); err != nil { return nil, err } return &PlaceOrderResponse{OrderID: id}, nil }
The users call, the database and the topic are all visible to the compiler and to Encore.

A notifications service subscribes with the same event type:

package notifications import ( "context" "encore.app/orders" "encore.dev/pubsub" "encore.dev/rlog" ) var _ = pubsub.NewSubscription(orders.OrderPlacedTopic, "send-receipt", pubsub.SubscriptionConfig[*orders.OrderPlaced]{Handler: SendReceipt}) func SendReceipt(ctx context.Context, e *orders.OrderPlaced) error { rlog.Info("sending receipt", "order", e.OrderID) return nil }

Key features

  • Service-to-service calls are function calls, so renaming a field breaks the build instead of a request in production.
  • Each service declares its own database, and tracing follows a request across calls, queries and published messages.
  • A deploy provisions the declarations in your own AWS or GCP account, such as RDS and SNS/SQS on AWS or Cloud SQL and Pub/Sub on GCP.
  • An agent moving an endpoint from one service to another gets compile errors at every caller it missed.

Good to know

Encore uses Go types as the contract rather than Protobuf, so non-Go consumers use the generated clients or the OpenAPI spec. When Encore provisions resources, the cloud access sits with Encore's IAM role, not the developer or agent changing a service.

Try Encore →

How to choose

  • gRPC-Go when many languages share Protobuf contracts.
  • Connect when you want Protobuf contracts that are also easy to call over HTTP.
  • Go kit for explicit layering with minimal magic.
  • Kratos for an opinionated layout across many services.

Microsoft's microservices architecture guide notes that each service is responsible for its own data persistence, which makes consistency across services a challenge, and the database per service pattern keeps a service's database private to that service. Whatever you pick, plan how every service gets its database and broker in each environment, and see the Encore Go docs for how services are defined.

Frequently asked questions

What is the best Go framework for microservices?

For RPC between services, gRPC-Go is the established standard and Connect is a simpler, HTTP-friendly option built on the same Protobuf definitions. Go kit offers transport-agnostic building blocks, and Kratos is a fuller framework with code generation and configuration. Encore is not a competing framework but an infrastructure SDK, where endpoints are Go functions, calls between services are type-checked function calls, and each service declares its own database and topics.

Do I need a framework for Go microservices?

No. Many teams use net/http with Protobuf or JSON contracts. A framework helps when you want shared conventions for transport, middleware, service discovery and observability across many services, so each team does not invent its own.

How do I call another service in Encore for Go?

Import the other service's package and call its API function with a context and a typed request. Encore turns the call into a network request between the services, so the compiler checks the request and response types while the services still deploy separately.

Is gRPC better than HTTP for Go microservices?

gRPC gives you a schema, generated clients and streaming, which helps when many services and languages talk to each other. JSON over HTTP is easier to debug and call from browsers. Connect supports both on the same handler.

Deploy to your cloud on AWS and Google Cloud
without managing infrastructure

Encore lets developers and agents define application infrastructure directly in code, then automatically provisions it from local development to production in your AWS or GCP account.

~/orders — claude
Claude Code
Claude Code v2.1.180Opus 5.5~/orders