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:
gRPC-Go generates servers and clients from Protobuf definitions, with streaming, deadlines and interceptors built into the protocol.
.proto file defines the contract for every language that calls the service.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.
Connect uses the same Protobuf definitions but serves them as net/http handlers that speak the Connect protocol, gRPC and gRPC-Web.
http.Handler values, so existing middleware applies.curl and JSON.Connect is a transport and contract layer, so service discovery, brokers and databases are still yours to set up.
Go kit separates each service into endpoints, transports and middleware, so the same business logic can be served over HTTP or gRPC.
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.
Kratos generates service layouts from Protobuf definitions and adds configuration, service registration and middleware.
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.
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
}
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
}
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.
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.
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.
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.
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.
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.