Awesome_IA_Rules / backend
Cursor rule1 starsChanged 3 days agoMITView on GitHub
Go backend engineering best practices, Clean Architecture, concurrency, error handling, and unit testing
Where files are headingNew Cursor rule files have more rules about planning and tracking tasks, and fewer about code style.
Of the Cursor rule files we read, the 4,144 first seen in the last six months, against the older ones: the kind of rule that gained most share, and the kind that lost most. About files like this in general, not this one, and an estimate, since a kind is a pattern in the words.
In this repository8 other files it gives its agents.
- AGENTS.mdAGENTS.md
- CLAUDE.mdCLAUDE.md
- .cursor/rules/backend/java-quarkus-backend.mdcCursor rule
- .cursor/rules/backend/node-bff-backend.mdcCursor rule
- .cursor/rules/core/01-core-engineering.mdcCursor rule
- .cursor/rules/core/02-spec-driven-development.mdcCursor rule
- .cursor/rules/core/03-code-review.mdcCursor rule
- .cursor/rules/frontend/node-react-frontend.mdcCursor rule
The file
We split this go-backend.mdc into the rules it gives an agent
7 rules. About 0 are common, 1 is distinctive, and 6 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈1
Distinctive · estimate
This author's own choices. Worth a look.
6
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Very specific: line 45
Always format with gofmt -s / goimports.
- Very specific: line 68
Always attach explicit timeouts (context.WithTimeout) to outbound database and network operations.
- Very specific: line 69
Check for context cancellation (errors.Is(err, context.Canceled) / context.DeadlineExceeded) before logging ERROR alerts for client-aborted …
- Distinctive: line 72
Default to synchronous execution.
- Very specific: line 73
Every spawned goroutine must have a deterministic termination path (errgroup.Group, sync.WaitGroup + ctx.Done()).
- Very specific: line 74
Prefer golang.org/x/sync/errgroup with errgroup.WithContext(ctx) and SetLimit(n) for bounded concurrent fan-out:
- Very specific: line 136
Builders & Table-Driven Tests: Use fluent test Builders for complex entities/DTOs and table-driven subtests (t.Run(tt.name, ...)) for input …
≈ “Common” is an estimate: at least 1 in 5 of the 6,668 Cursor rule files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
---
description: "Go backend engineering best practices, Clean Architecture, concurrency, error handling, and unit testing"
globs: "**/*.go"
alwaysApply: false
---
# Go Backend Engineering Standards
> **Scope**: All Go (`*.go`) source and test files.
> **Mandate**: Write idiomatic, readable, boring Go code following Clean Architecture, explicit context propagation, structured error handling, and leak-free concurrency.
---
## 1. Project Structure & Clean Architecture
Enforce strict inward dependencies: `entrypoint/infrastructure → application → domain`.
```text
cmd/api/main.go # Thin bootstrap calling runner
configs/ # Typed config structs, loader, YAML/env bindings
internal/
├── domain/ # Pure business logic (zero external/infra imports)
│ ├── entities/ # Aggregate roots & entities protecting invariants
│ ├── vo/ # Immutable Value Objects (e.g., Money, Email)
│ ├── services/ # Cross-entity stateless domain services
│ └── ports/ # Stable business capability interfaces (Repositories)
├── application/ # Use case orchestration & CQRS
│ ├── commands/ # Write handlers (Create, Update, Delete)
│ ├── queries/ # Read handlers (when business visibility rules apply)
│ ├── dtos/ # Request (Validate) & Response (FromEntity) DTOs
│ └── ports/ # Use-case-specific external ports (Gateways, Readers)
└── infrastructure/ # Technical implementations
├── entrypoint/rest/ # HTTP handlers, routers, middlewares
├── entrypoint/consumer/ # Message queue consumers
├── repository/ # DB implementations, persistence DTOs, mappers
├── adapter/ # External HTTP/gRPC client implementations
└── runner/ # Dependency wiring & graceful shutdown
```
---
## 2. Idiomatic Go & Code Style
### Formatting & Imports
- Always format with `gofmt -s` / `goimports`.
- Group imports into three blocks separated by blank lines:
1. Standard library (`"context"`, `"fmt"`, `"time"`)
2. Third-party dependencies
3. Internal project packages
### Naming Conventions
- **Packages**: Short, concise, lowercase, single-word nouns (`payment`, `order`, `postgres`). Never use `util`, `common`, `helpers`, or `base`.
- **Interfaces**: Define interfaces on the **consumer side**, kept small (1–3 methods). Do not create interfaces preemptively without a concrete need for polymorphism or boundary mocking.
- **Strong Domain Typing**: Define explicit types for domain identifiers and statuses (`type OrderID string`, `type OrderStatus string`) instead of bare primitives.
### Pointers vs. Values
- **Use Pointers (`*Entity`)**: For domain entities, aggregate roots, large structs, and repository lookups where `nil` semantics or state mutation apply.
- **Use Values (`ValueObject`)**: For small, immutable Value Objects (`Money`, `DateRange`) and primitives.
- **Slices**: Return an initialized empty slice (`[]Item{}`) rather than `nil` in collection responses so JSON serialization produces `[]` instead of `null`.
---
## 3. Context & Concurrency
### `context.Context` Rules
- Pass `ctx context.Context` as the **first parameter** of every function performing I/O, orchestration, or long computation.
- **Never** store `context.Context` inside a struct.
- Always attach explicit timeouts (`context.WithTimeout`) to outbound database and network operations.
- Check for context cancellation (`errors.Is(err, context.Canceled)` / `context.DeadlineExceeded`) before logging `ERROR` alerts for client-aborted requests.
### Safe Concurrency
- Default to synchronous execution; introduce goroutines **only** when concurrent I/O or parallelism yields measurable latency/throughput gains.
- Every spawned goroutine must have a deterministic termination path (`errgroup.Group`, `sync.WaitGroup` + `ctx.Done()`).
- Prefer `golang.org/x/sync/errgroup` with `errgroup.WithContext(ctx)` and `SetLimit(n)` for bounded concurrent fan-out:
```go
g, gCtx := errgroup.WithContext(ctx)
g.SetLimit(10) // Always bound concurrency
for _, item := range items {
g.Go(func() error {
return s.processItem(gCtx, item)
})
}
if err := g.Wait(); err != nil {
return err
}
```
### Resource Lifecycle
- Immediately `defer rows.Close()`, `defer resp.Body.Close()`, or `defer tx.Rollback()` after checking the acquisition error.
- Instantiate database pools (`*sql.DB`) and HTTP clients (`*http.Client`) **once** at startup and reuse them across requests.
---
## 4. Validation & Error Handling
### Two-Tier Validation with Aggregated Errors
Aggregate all validation failures at once (using `errors.Join` or `multierror`) so callers receive complete feedback in a single round-trip:
```go
func (r *CreatePaymentRequest) Validate() error {
var errs []error
if r.CustomerID == "" {
errs = append(errs, errors.New("customer_id is required"))
}
if r.Amount <= 0 {
errs = append(errs, errors.New("amount must be greater than zero"))
}
if len(r.Currency) != 3 {
errs = append(errs, errors.New("currency must be a 3-letter ISO code"))
}
if len(errs) > 0 {
return apperror.BadRequest("validation failed", "VALIDATION_ERROR", errors.Join(errs...))
}
return nil
}
```
### Domain Entity Isolation
- Domain structs must **never** carry `json`, `bson`, `db`, or `gorm` tags.
- Repositories must map between `domain.Entity` and an internal `PersistenceModel` struct (`MapEntityToModel` / `MapModelToEntity`).
### Error Creation & Proximity Logging
- **Domain**: Returns semantic errors (`BadRequest`, `Conflict`, `NotFound`) without logging.
- **Infrastructure (Repositories / Adapters)**: Logs technical failures once at the source using structured logging (`slog.ErrorContext(ctx, "failed to save payment", slog.Any("err", err), slog.String("payment_id", id))`) and returns a safe domain/application error wrapping the cause.
- **Application (Handlers)**: Propagates repository/adapter errors upward **without re-logging**.
- **Entrypoint (HTTP Handlers & Error Middleware)**: Logs `4xx` client/validation rejections once at `WARN` (either at the validation boundary or in centralized error middleware, never both) and logs only unlogged unexpected `500` errors at `ERROR`. Never leak `sql.Err*` or raw driver errors to clients.
---
## 5. Unit Testing (`*_test.go`)
- **Naming**: `Test<Struct>_<Method>_Should<Expected>_When<Condition>`.
- **Pattern**: Strictly follow **Arrange-Act-Assert (AAA)** using `testify/require` (for preconditions that must halt the test) and `testify/assert` (for result verification) with descriptive English messages.
- **Builders & Table-Driven Tests**: Use fluent test Builders for complex entities/DTOs and table-driven subtests (`t.Run(tt.name, ...)`) for input validation, domain invariants, and mapper edge cases.
- **Mocks**: Generate mocks for ports using `uber-go/mock` (`gomock`). Avoid blanket `gomock.Any()` when specific argument matchers or `.DoAndReturn()` assertions verify state transitions.
- **Determinism**: Inject a `Clock` interface (`type Clock interface { Now() time.Time }`) instead of calling `time.Now()` directly. Use `t.Parallel()` on isolated unit tests.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

