AL+

Language: RO (română) EN (English)

Email us: paul@alplustech.com

Looking back at the week of 25 September–1 October 2024

Small Go services still need explicit HTTP behavior

Go routing and sqlc can keep request and query code visible. Evaluate redirects, access checks and database work before calling the smaller stack simpler.

Citiți articolul în română

A small Go web service can keep much of its behavior visible in ordinary handlers and SQL. That is useful when the team understands both interfaces. It also means the team must deliberately own request semantics and database behavior that a framework might otherwise organize. Count the work needed to explain a complete operation, rather than the dependencies omitted from the build.

Julia Evans's 27 September 2024 web development notes describe that appeal alongside a concrete redirect problem and her use of sqlc. This November 2026 retrospective examines those boundaries. Her experience is evidence of one developer's workflow, not a benchmark or a guarantee that this stack simplifies every service.

The router feature was already available

Go 1.22 added method matching and path wildcards to net/http routing. The Go team's 13 February 2024 explanation establishes that this was earlier functionality discussed in September, not a release that week. It also explicitly leaves third-party frameworks as a reasonable choice for advanced routing needs.

A route pattern can express the method and path shape, while the handler receives the matched identifier. That removes some hand-written dispatch code. The special treatment of GET, which also matches HEAD, is part of the documented contract. Neither a method pattern nor a path variable establishes whether a recognized user may read the identified record.

For a proposed customer export endpoint, define the operation before choosing the handler arrangement. Who can request the export? Which customer's data is selected? What happens if the requested identifier belongs to someone else? These are illustrative design questions. Moving dispatch into the standard router helps with matching; it does not answer the business authorization questions.

A slash can change the operation

Evans reports a POST to a path without the trailing slash being redirected to the slash form and becoming a GET, losing the body in her observed flow. It does not establish that every redirect, HTTP client or Go request changes method. The consequential point is that normalization and client redirect behavior are part of the endpoint contract.

A proposed integration might submit a new order to the wrong path spelling. If the client follows a redirect into a different operation, the server can return a plausible response without creating the intended order. A friendly page is poor evidence of success. The integration needs an unambiguous result tied to the requested change.

Choose canonical paths deliberately, including what the other spelling does. Inspect requests through the actual proxy and client arrangement. Check method, body and authentication handling after a redirect when redirects are supported. These are proposed acceptance checks, not a reproduced Go bug or a recommendation to replace every normalization redirect.

For an API, rejecting a mistaken path can be clearer than silently redirecting a mutation. Browser navigation may have a different usability requirement. Keep the distinction visible instead of applying a single “clean URLs” rule across all endpoints. Compatibility with existing callers can also outweigh a preferred new naming convention.

Generated SQL code keeps SQL as the source

In the same September account, Evans describes writing a query and reading the Go function generated by sqlc. That dates her use of the approach; it does not date sqlc's first release. The sqlc 1.31.1 overview, consulted as later versioned documentation, describes generating typed Go interfaces from SQL. Its version is not presented as the September 2024 toolchain.

This arrangement can suit a team that wants to review the actual query rather than reconstruct it from an ORM expression. The generated call makes parameters and result handling explicit in Go. The useful boundary is a reviewed query and a reproducible generated interface. It is not a promise that every database-related error becomes a compilation error.

Suppose a proposed operation changes an order and records an audit entry. Two generated methods do not automatically make those changes atomic. The application still needs a transaction boundary and a decision about what to do when an external notification fails. SQL generation reduces mapping work; it does not define the business operation's failure semantics.

Likewise, a typed query can return another customer's row if its conditions express the wrong rule. Inspect predicates and callers together. Query plans, indexes and production-sized data determine whether the operation is fast enough. Generating the call cannot guarantee a useful execution plan or prevent a workload from creating lock contention.

The smaller stack still has an operating model

The release process should keep schema changes, query sources and generated code consistent. Pin the generator used for the project, regenerate deliberately and inspect relevant changes. Decide how an application version behaves while a database migration is being rolled out. A compilable binary alone cannot prove compatibility with the database it will encounter.

Resource ownership remains visible too. Give requests sensible deadlines and establish how database work is cancelled or bounded. Size connection use for the actual database and concurrency pattern. Evans's SQLite notes concern her small programs; copying a connection setting into a different database or workload would require a new justification.

No universal performance comparison follows from these choices. A service with a handful of stable queries differs from one with user-defined filtering, extensive administrative screens or complex background processing. The amount of custom infrastructure needed around handlers can dominate the apparent saving in router and query boilerplate.

A framework can be the economical choice

The strongest counterargument is that conventions are valuable. A team already fluent in a framework may get clearer authentication, validation and integration through its established structure. Rebuilding those conventions as local helpers can produce an undocumented framework with fewer maintainers. Keeping an existing working stack may therefore be the simpler operating decision.

Choose the standard-router and generated-SQL approach when the workload is bounded and the team can explain the full request-to-query path. For custom software, ask for one important operation to be traced through routing, access, transaction handling and its response to failure. That trace gives “small” a meaning the business can assess.