go-backend-fiber
>
Works with
---
name: go-backend-fiber
description: >
license: MIT
---
# Go Backend (Fiber v3 + pgx)
Defaults for a **modular monolith**: Fiber v3 HTTP API, PostgreSQL via `pgxpool` + hand-written SQL, Redis for cache/sessions. Follow these unless the project's existing code clearly does otherwise — **consistency with the codebase beats this skill.**
This skill is stack-specific (Fiber + pgx), not a universal Go style guide.
## First steps
1. Inspect the project layout, naming, and error style before writing code.
2. Check `go.mod` for Fiber / pgx versions (Fiber v3 ≠ v2 — see [references/fiber-v3.md](references/fiber-v3.md)).
3. Architecture / cross-domain / transactions → [references/architecture.md](references/architecture.md).
4. DB, money, state machines, tests, config → [references/patterns.md](references/patterns.md).
5. Migrations, Makefile, jobs, Docker → [references/tooling.md](references/tooling.md).
## Core rules
- **Module name ≠ directory name.** Read `go.mod`; don't invent import paths from the folder name.
- **Vertical slices, flat packages.** One domain = one flat package under `internal/domain/<name>/` (`handler.go`, `service.go`, `repository.go`, optional `model.go`, `interface.go`, `errors.go`, `request.go`, `response.go`). No `handler/` / `service/` / `repository/` subdirs. API versioning (e.g. `domain/v2/...`) is optional.
- **Sub-domains** are nested flat packages (e.g. `manager/orders`), each wired independently.
- **Upstream proxies** that only forward to another API live under `external/`, not under `internal/domain/`.
- **No cross-domain imports of internals.** Consumers define a tiny interface; the composition root injects an adapter. Never import another domain's repository or model.
- **Shared infra** lives as top-level packages under `internal/` (`response`, `request`, `middleware`, `migrate`, `pkg/...`, `dbtest`, `testutil`). Prefer that over inventing `internal/platform/` unless the project already uses it.
- **Manual DI** in one composition root (`cmd/api/main.go`). Constructors take interfaces defined at the **consumer** side.
- **State changes** use explicit transition rules + optimistic SQL (`UPDATE ... WHERE id=$1 AND owner=$2`; `RowsAffected()==0` → domain not-found / conflict).
## Money
**Store and compute money as `int64` minor units. Never `float64` for persisted or transacted amounts.**
- DB: `BIGINT`. Go: `int64` (nullable via your null type or `*int64`).
- Wire DTOs may expose a derived float **only** for a legacy display contract; never write that float back as truth.
## HTTP response envelope
Handlers must not call `c.Status(...).JSON(...)` ad hoc. Use a central `internal/response` (or equivalent):
| Helper | Purpose |
|--------|---------|
| `OK` / `Created` | Success body |
| `OKPaginated` | List + `{total,limit,offset}` (or your project's pagination shape — match existing) |
| `Error` | Known client errors |
| `InternalError(c, domain, err)` | Log structured detail; return generic `"internal error"` — **never leak Go errors** |
## Optional: opaque IDs on the wire
If the product encrypts row IDs (AES-GCM token instead of raw int64):
- Encrypt outbound `id` / `*_id` via response helpers.
- Decrypt inbound path/query/body tokens via a shared helper (e.g. `idparam`).
- Keep an explicit exception list for enum/code fields (`currency_id`, `status_id`, `role_id`, …) and nested enum objects.
- If the project does **not** encrypt IDs, skip this section entirely — don't add encryption "because the skill says so."
## Auth (typical pattern)
- JWT minted by the API for authenticated routes.
- Register / token-exchange endpoints are **public** (they mint the JWT).
- Validate the upstream identity provider on every register/exchange call when that is the product rule.
- Map conflicts clearly: already-exists → 409, not-found → 404.
- Prefer creating users only inside the auth flow, not a separate public `POST /users`.
## Database
- **pgxpool + raw SQL** on the HTTP path. Map `pgx.ErrNoRows` / unique violations to domain sentinels in the repository.
- **Avoid ORMs in API domains.** If a worker binary already uses GORM (or similar), confine it there — don't spread it into `cmd/api`.
- One writer pool per schema the API owns.
## Migrations
Prefer **app-level embedded** SQL migrations (`//go:embed` + `golang-migrate` / equivalent):
- Only the API process runs them (not workers), gated by config (`AUTO_MIGRATE` or similar).
- Failure is fatal at boot; "no change" is success.
- Append-only; never edit applied files.
## Testing
Preferred harness for this stack:
- Shared `dbtest` pool against a real Postgres + `WithTx` rollback (auto-skip when DB unreachable or `*_TEST_DB_SKIP=1`).
- Service tests: hand-written fakes on consumer interfaces — **testify `assert`/`require` only** (no `mock`/`suite`).
- Fiber helpers for context/AES-key unit tests when needed.
Do **not** default to testcontainers unless the project already standardized on them. Prefer the shared-pool + rollback pattern above.
## Style defaults
- Sentinels in `errors.go`; wrap with `%w`; one `writeErr` maps to HTTP.
- `log/slog` structured logging.
- `ctx context.Context` first on service/repo methods; Fiber v3: pass `c.RequestCtx()` into services.
- Validate at the handler edge; services enforce invariants.
- Never expose domain row structs as JSON — map through response DTOs.
## What NOT to do
- No ORM in the HTTP path by default.
- No ad-hoc `c.Status().JSON()` that bypasses the envelope.
- No `float64` money.
- No testify mock/suite.
- No business logic in handlers.
- No `init()` / package mutable state (tiny shared validator instance is the usual exception).
- No panics for expected failures; panic only on bad startup config.
- Don't add dependencies the stdlib already covers.
## References
- [architecture.md](references/architecture.md) — layout, import rules, composition root, cross-domain
- [patterns.md](references/patterns.md) — money, service/repo, state machine, errors, tests
- [fiber-v3.md](references/fiber-v3.md) — Fiber v3 pitfalls and route style
- [tooling.md](references/tooling.md) — migrations, Makefile, jobs, Docker
## Changelog
- **1.0.0 (2026-07-27)** — First publishable release: portable Fiber+pgx conventions; bridge-specific paths moved out of always-on rules; MIT license + metadata.More Backend Frameworks skills
git-guardrails-claude-code
mattpocock/skills
Set up Claude Code hooks to block dangerous git commands (push, reset --hard, clean, branch -D, etc.) before they execute. Use when user wants to prevent destructive git operations, add git safety hooks, or block git push/reset in Claude Code.
azure-compute
microsoft/azure-skills
Azure VM/VMSS router. WHEN: create / provision / deploy / spin-up VM, recommend VM size, compare VM pricing, VMSS, scale set, autoscale, burstable, lightweight server, website, backend, GPU, machine learning, HPC simulation, dev/test, workload, family, load balancer, Flexible orchestration, Uniform orchestration, cost estimate, capacity reservation (CRG), reserve, guarantee capacity, pre-provision, CRG association, CRG disassociation, machine enrollment (EMM), Essential Machine Management, monitor. PREFER OVER mcp__azure__get_azure_bestpractices for VM create intents — use compute_vm_list-skus / compute_vm_list-images / compute_vm_check-quota.
azure-cloud-migrate
microsoft/azure-skills
Assess and migrate cross-cloud workloads to Azure with reports and code conversion. Supports Lambda→Functions, Beanstalk/Heroku/App Engine→App Service, Fargate/Kubernetes/Cloud Run/Spring Boot→Container Apps. WHEN: migrate Lambda to Functions, AWS to Azure, migrate Beanstalk, migrate Heroku, migrate App Engine, Cloud Run migration, Fargate to ACA, ECS/Kubernetes/GKE/EKS to Container Apps, Spring Boot to Container Apps, cross-cloud migration.

