Skip the infrastructure sprint.

Databases, auth, scheduling, and queues — configured, not built. Self-hosted, and licensed with a signed file instead of a server checking in on you.

Get a license Free to try. No card.

What you don't have to build.

None of this is a plan for the future — every row below is a real, working part of gist today. The column on the right is what actually replaces the column on the left in your project.

Normally, you'd buildWith gist, you get
A database layer, plus OpenAPI docs that drift from it the first time someone forgets to update bothOne Go struct — decoding, validation, docs, and the MCP tool schema, all from the same source
A job scheduler service, deployed and monitored on its ownOne gist-scheduler config block
Retry/nack logic for a message queue consumerReturn an error from your handler — gist requeues it
A staging database that quietly drifts from what production actually looks likeA real container, seeded from your own fixtures — your code can't tell it from prod
A second integration project to make your API callable by an AI agentOne config flag — the same contract is already an MCP tool
Hand-rolled batching to cut database round trips before a launchNewBatch() — several queries, one round trip, built in

Fourteen services, one config file, one binary — see "The gist" below for the rest.

How it works.

Application developers write business logic. Gist takes responsibility for everything that's repetitive infrastructure.

Your Go code — owns

  • Business logic
  • Domain objects
  • API handlers
  • State-machine actions
  • Custom services
gistsdk API, local gRPC/IPC

gist-server — owns

  • HTTP/API
  • MySQL · PostgreSQL
  • Elasticsearch · GCS · RabbitMQ
  • State-machine graph · scheduling
  • Logging · infrastructure lifecycle

The application does not need to know how infrastructure is connected.

Gist-server owns infrastructure mechanics; Go owns application semantics. Your app deals in typed Go objects and callbacks — business logic, handlers, state. Everything ugly about talking to a database, a queue, or a bucket lives one process away, in gist-server.

That split buys real advantages, not just tidiness:

API-first.

OpenAPI docs are generated straight from the Go types your handler already uses for decoding and validation — the same struct does both jobs, so there's nothing separate to keep in sync. The Go type is part of the API contract.

type CreateOrderInput struct {
    CustomerID int `json:"customer_id" required:"true" example:"42"`
}

var CreateOrder = gistapiserver.EndpointHandler("create-order",
    []gistapiserver.ExpectedError{gistapiserver.Internal},
    func(sg Services, ctx context.Context, in CreateOrderInput, out *CreateOrderOutput) error {
        out.OrderID = sg.Orders.Create(ctx, in.CustomerID)
        return nil
    },
    &CreateOrderOutput{OrderID: "ord_9f2a"},
)

gistapiserver.Attach("orders-api", CreateOrder)

Rename a field or add required:"true", and both the validation and the docs change together — they were never two things to begin with.

Under the hood, CreateOrder is a remote procedure call disguised as an ordinary Go function — you never wrote any RPC code, gist did.

Built-in mocking means the contract can exist before the implementation does:

Design the contract first, hand it to the frontend, wire in real logic whenever it's ready — the docs never drift, because there was never anywhere else for them to live.

Also an MCP server.

An endpoint's input schema, output shape, description, and examples already exist for one reason: to generate its docs. That's also everything an AI agent needs to call it correctly. Set one field, and the same definition becomes a tool — nothing new to write, nothing extra to keep in sync.

Go CreateOrder handler
a person, over HTTP
REST + OpenAPI docs
an agent, over MCP
tools/call
{
  "id": "create-order",
  "path": "/orders",
  "enable-mcp": true
}

That's the entire integration. create-order now shows up in tools/list with the same input schema, description, and example the REST docs already show — opt-in per endpoint, so nothing is exposed you didn't ask for.

One example.

Three ordinary things that happen to the same order, each triggered a different way — an HTTP request, a scheduled job, a queue message. All three land in your Go code; gist is just how they got there.

A customer places an order:

POST /v1/orders
gist-api-server
validate, auth, route
Go CreateOrder handler
save the order
gist-mysql-client
charge the card
gist-http-client
index for search
Elasticsearch
store the receipt
GCS
advance order state
state machine

Two more ways the same order gets touched, same shape either way:

03:00, every night
scheduler
Go reconciliation func
order shipped
RabbitMQ → gist-server
Go event handler

Infrastructure owns delivery; application owns processing — return an error from the handler and gist-server nacks and requeues the message for you, no retry logic to write.

Performance.

That extra hop has a real cost — measured, not guessed, at three different scales: a single database point lookup, direct versus through gist.

Queries Direct Through gist Overhead
1,000 0.503 ms 0.560 ms +0.057 ms
10,000 0.504 ms 0.559 ms +0.055 ms
100,000 0.505 ms 0.551 ms +0.046 ms
10 × 1,000 (parallel) 0.117 ms 0.147 ms +0.030 ms

Per-query cost, single-row MySQL point lookups. The overhead is a flat per-call cost — it doesn't compound with volume, and there's no network involved either way: gist-server runs on the same machine, so this is a local unix-socket round trip, not a remote call. The last row swaps one query at a time for 10 concurrent callers, which is why both columns drop together — most of a query's cost is time spent waiting on the database, and concurrent callers overlap that wait instead of stacking it up.

Measured on an Apple M4 Pro, Go 1.27, MySQL 9.7.2 in a local Docker container — a development laptop, not a dedicated rig, but the same one for every row above.

That per-call cost is fixed — pay it once per round trip, not once per query. A request that needs two related reads can ask for both in one call instead of two:

b := db.NewBatch()
var total int64
var items []Order
b.Count[Order](&total, gistmysql.WithConditions(cond))
b.Find[Order](&items, gistmysql.WithConditions(cond), gistmysql.WithLimit(50))
b.Run(ctx)
Same request Round trips Measured
Two separate calls 2 1.7 ms
One batched call 1 0.88 ms

A paginated list endpoint — a count and a page of rows, the two queries almost every list view needs. Works for writes too: several inserts in one transaction still cost one round trip, and each one's own result comes back labeled, so a failure tells you exactly which one.

The gist.

An application operating system for Go services.

Pricing.

Same binary either way — the license file is what changes.

License

$299/mo

All 14 built-in services, no usage caps. No custom services included.

Get a license

Custom services

from $50/mo each

Optional, on top of a license — priced per service, cheaper the more you run:

  • 1st–4th service$100/mo each
  • 5th–9th service$75/mo each
  • 10th on$50/mo each
Add custom services

Every license begins as a free, hour-long trial — nothing is held back.