S/02 · Services
APIs & backends
The part nobody sees, built to never be noticed.
REST and gRPC APIs, webhooks, background jobs and integrations, written in Go. Fast, cheap to run and boring in the best way — they keep working while everything around them changes.
- Language
- Go
- Interfaces
- REST, gRPC, webhooks, events
- Comes with
- Tests, docs, dashboards
- 01
Your website, app and admin each need the same data.
- 02
The current backend is slow, fragile or too expensive to run.
- 03
You depend on third-party services that fail in creative ways.
- 04
Your team needs an API it can understand and extend.
- D/01
A documented API
We write the contract before the code: every endpoint, field and error, in OpenAPI or protobuf. Your web, app and partner teams can build against it from day one, and the documentation is generated from the same file, so it always matches what the server does.
Included
- The full contract in OpenAPI 3 or protobuf
- A working example for every endpoint
- Error codes that say what went wrong and what to do
- Versioning rules, so changes don’t break old clients
api/openapi.yaml POST /v1/orders · Create an order
Shop API · v1.4
Request
- items: a list of { sku, qty }, at least one.
- Idempotency-Key header: the same key never creates two orders.
Responses
- 201 Created: the order, with a Location header.
- 409 out_of_stock: which SKU, and how many are left.
- 422 invalid_items: one error per field.
Errors
- Every error body has the same shape: { code, message, field }.
Auth
- Bearer token; scope orders:write.
- D/02
Data done properly
We design PostgreSQL tables around the queries your product actually runs, with constraints that keep bad data out at the source. Every change is a versioned migration, so the schema in production is always the one in the repository.
Included
- A schema with keys, constraints and comments
- Versioned migrations that run forward and back
- Indexes checked against real query plans
- Backups and a restore that has been tested
migrations/0004_orders.sql - D/03
Background work
Anything slow or unreliable moves out of the request: sending receipts, syncing stock, building reports. Jobs go through a queue, failed ones retry with backoff, and the ones that keep failing land somewhere a person will see them.
Included
- A queue and workers sized for your load
- Scheduled jobs written in code, not hidden in a crontab
- Retries with backoff, and jobs that are safe to repeat
- A dead-letter queue, with an alert when it fills
docs/jobs.mmd - D/04
Integrations
Every outside service gets a thin wrapper with its own timeouts, retries and fallback. When the payment or SMS provider has a bad day, your orders wait or switch routes instead of failing, and you can swap a provider without touching the rest of the code.
Included
- A small adapter per provider, behind one interface
- Timeouts, retries and a fallback for each
- Webhook handlers that check signatures and ignore duplicates
- Fake providers for tests, so nothing calls the real one by accident
internal/integrations/README.md Provider Timeout Retries When it fails Payments 5 s 3, backoff Order stays pending; a job checks again SMS 3 s 5, backoff Switches to the second provider Email 10 s 5, backoff Queued; the order is not held up Maps 2 s 1 Cached result, then postcode only Shipping 8 s 3 Label made later; the customer is told - D/05
Observability
Every request leaves structured logs, metrics and a trace you can follow across services. Dashboards show the few numbers that matter, and alerts fire on what users feel, such as a slow checkout or a growing queue.
Included
- Structured JSON logs with request IDs
- Metrics and traces through OpenTelemetry
- Dashboards for latency, errors, traffic and queues
- Alerts with a short note on what to check first
grafana · shop-api p95 latency
42 ms
target under 150 ms
Error rate
0.03%
5xx, last 24 hours
Throughput
280/s
peak, Friday evening
Queue lag
1.8 s
alert above 30 s
- D/06
Tests & CI
Unit tests cover the logic, integration tests run against a real PostgreSQL in a container, and both run on every push. A change that breaks a test, fails the linter or skips a migration does not get merged.
Included
- Unit tests for business rules and edge cases
- Integration tests against real databases and queues
- A pipeline that lints, tests and builds the container
- Race detection and coverage on every run
ci · pipeline #482 $ go vet ./... && staticcheck ./...
✓ no issues
$ go test -race -cover ./...
✓ 412 passed · coverage 81%
$ go test -tags=integration ./internal/store
× TestReserveStock: stock went below zero
! merge blocked until the pipeline is green
- 01
Contract first
We design the API with the people who will call it, before writing the code behind it.
- 02
Build in slices
Each slice works end to end — database to endpoint — and is deployed early.
- 03
Load & failure tests
We push it past expected traffic and pull its dependencies out from under it.
- 04
Hand over
Runbooks, dashboards and a walkthrough, so your team owns it with confidence.
A new backend usually takes eight to twelve weeks, and the first working slice is live within three. You see it running on a staging server every week, so you can judge real progress instead of a status report.
- Week 1
The API contract, written with the people who will call it, and the data model behind it.
- Weeks 2–3
The first slice from database to endpoint, deployed to staging with CI in place.
- Weeks 4–8
The remaining slices, integrations and background jobs, each shipped when it works.
- Weeks 9–10
Load and failure tests, then dashboards and alerts tuned to what we learned.
- Weeks 11–12
Launch, runbooks and a walkthrough with your team.
The code
The full repository, with its history, in your own Git account.
The API contract
OpenAPI or protobuf files, with generated docs and client libraries.
Database migrations
Every schema change as a versioned file that can rebuild the database from empty.
Dashboards and alerts
Exported as code, so they move with the service to any environment.
Runbooks
What to do when an alert fires, how to deploy, roll back and restore.
A month of support after launch
We stay on call for questions and fixes while your team settles in.
- Go
- PostgreSQL
- Redis
- NATS
- gRPC
- OpenAPI
- OpenTelemetry
- Docker
Why Go?
It compiles to one small binary, handles heavy traffic on modest hardware, and stays readable for whoever maintains it next.
Can you work with our existing backend?
Yes. We often put a clean API in front of a legacy system and replace it piece by piece.
Who hosts it?
You do, we do, or we set it up on your cloud. Everything ships as containers with the infrastructure as code.
How long does it take?
Eight to twelve weeks for most new backends. A clean API in front of an existing system can be live in four.
Can our own developers take it over?
Yes, and we plan for it. The code is plain Go with few dependencies, and the tests, docs and runbooks are written for whoever reads them next.
Tell us what you are building.
Every project starts with a consultation: you bring the idea and everything you know, we turn it into a design you can build on.
Book a consultation