NestGo FAQ: Common Questions About the NestJS-Style Go Framework

Answers to the questions developers ask most when evaluating NestGo, a NestJS-inspired web framework for Go (Golang). For a full feature walkthrough, start with Getting Started.

Is NestGo a port of NestJS?

No. NestGo is inspired by NestJS but is not a line-by-line port — Go has no decorators or runtime metadata, so a literal port would fight the language. NestGo keeps the NestJS architecture (controllers, guards, interceptors, pipes, exception filters, modules, dependency injection) and re-expresses it with Go idioms: interfaces, generics, and explicit registration. The request lifecycle is the same one NestJS developers know — Filters → Guards → Interceptors → Handler. See the full concept mapping in NestGo vs NestJS.

What is the best NestJS alternative for Go?

If what you liked about NestJS was its structure — modules, DI, guards, and a clean controller pattern — NestGo is built specifically to be that: a NestJS-style architecture on top of proven Go HTTP engines (Gin or Fiber). Plain Gin or Fiber are excellent routers but leave architecture entirely to you; NestGo adds the missing layer (DI via uber/fx, guards, interceptors, pipes, exception filters, versioning, lifecycle hooks) without hiding the engine underneath. Its core package has zero dependencies, so adopting it does not lock your handlers to any HTTP library.

Does NestGo work with Gin?

Yes. Gin is one of the two officially supported adapters, published as a separate module:

go get github.com/ashrafAli23/nestgo-gin-adapter
app := di.NewApp(config, ginadapter.New, /* modules */)

All NestGo features — guards, interceptors, pipes, filters, middleware, SSE — behave identically on Gin. When you need a Gin-specific feature, c.Underlying() returns the raw gin.Context. See Adapters.

Does NestGo work with Fiber?

Yes. Fiber (built on fasthttp) is the second official adapter:

go get github.com/ashrafAli23/nestgo-fiber-adapter
app := di.NewApp(config, fiberadapter.New, /* modules */)

Because handlers only ever see the core.Context interface, switching between Gin and Fiber is literally a one-line change in main.go — no handler, guard, or middleware code changes.

How does dependency injection work in Go without decorators?

NestGo uses uber/fx for constructor-based dependency injection. Instead of @Injectable(), you write a plain constructor function — fx inspects its parameter types and wires the graph at startup:

func NewUserService(repo *UserRepo) *UserService { ... }
func NewUserController(svc *UserService) *UserController { ... }

fx.Module("users",
    fx.Provide(NewUserService),
    fx.Provide(di.AsController(NewUserController)),
)

di.AsController tags the constructor so NestGo auto-registers its routes. A missing dependency fails at application boot with a clear error, not at request time. Details in Dependency Injection.

Is NestGo production ready?

NestGo ships the operational features production services need: graceful shutdown with request draining, TLS via Config.TLSCertFile/TLSKeyFile, Kubernetes health and readiness probes (Config.HealthCheck/ReadinessCheck), panic recovery, rate limiting, W3C traceparent distributed tracing, idempotency keys for safe retries, and structured logging you can back with zerolog, slog, or zap. It is also a young framework compared to NestJS, so evaluate it against your requirements and pin your versions. The risk profile is deliberately low: the core is interfaces with zero dependencies, and the HTTP heavy lifting is done by Gin or Fiber, both battle-tested in production for years.

How do I validate request bodies in NestGo?

Two complementary mechanisms. For struct-tag validation (the class-validator equivalent), plug in the optional nestgo-validator module once:

core.SetValidateFunc(validator.Validate)

type CreateUserDTO struct {
    Name  string `json:"name"  validate:"required,min=3,max=50"`
    Email string `json:"email" validate:"required,email"`
}

Every DTO extracted with core.B[T]() or core.QDto[T]() is then validated automatically. For custom business rules, implement Validate() error on the DTO — tags run first, then your method. Failures return structured 400/422 errors before your handler runs. See Validation and Extractors.

Can I use standard net/http middleware with NestGo?

Not directly. NestGo middleware has the signature func(core.HandlerFunc) core.HandlerFunc and operates on the adapter-neutral core.Context, not on http.Handler — that is what lets the same middleware run on both Gin (net/http) and Fiber (fasthttp). In practice most needs are covered by the built-in middleware package (CORS, Helmet, rate limiting, CSRF, compression, ETag, timeouts, and more), and porting a net/http middleware is usually a few lines of wrapping its logic in a MiddlewareFunc. As an escape hatch, c.Underlying() exposes the raw gin.Context or fiber.Ctx for adapter-specific integration — note that net/http middleware can never run on the Fiber adapter, since Fiber is not built on net/http.

How do I do graceful shutdown in NestGo?

It is built in. NestGo listens for SIGINT/SIGTERM, stops accepting new connections and drains in-flight requests for up to Config.ShutdownTimeout, then runs your Config.OnShutdown hooks, and finally calls the OnModuleDestroy lifecycle hooks — so dependencies close only after no requests are being served:

config.OnShutdown = []func(ctx context.Context) error{
    func(ctx context.Context) error { db.Close(); return nil },
}

For per-service cleanup, implement OnModuleDestroy(ctx context.Context) error and register the constructor with di.AsDestroyHook — the DI container calls it during shutdown. See Lifecycle Hooks.

What Go version does NestGo require?

Go 1.25.14 or later. Older 1.25.x toolchains are upgraded automatically through the go directive in go.mod, so in practice you just need a Go 1.25 installation. The patch level is deliberate: 1.25.14 includes Go standard-library security fixes, and NestGo’s generics-based extractor API relies on a modern toolchain anyway.

How fast is NestGo? What is the overhead over raw Gin or Fiber?

NestGo is a thin layer, and the parts that could cost performance were designed around: the request path avoids reflection (extractors are plain generic function calls resolved at compile time — the one exception is QDto[T](), which reflects over struct tags to bind query parameters), the Gin adapter pools contexts while the Fiber adapter deliberately spends one small per-request allocation in exchange for a reliable use-after-release guard, CORS and Helmet headers are pre-computed at init, and the rate limiter is sharded 32 ways to reduce lock contention. The per-request overhead is a small constant — a few interface calls and extractor closures on top of the underlying engine — so throughput remains dominated by Gin or Fiber themselves plus your own handler work (JSON encoding, database calls). If a specific route is truly hot-path critical, you can always register a raw core.HandlerFunc without extractors.

How do I migrate from plain Gin or Fiber to NestGo?

Incrementally. A Gin or Fiber handler maps to a core.HandlerFunc — func(c core.Context) error — and c.Underlying() still gives you the raw gin.Context or fiber.Ctx while you transition, so nothing forces a big-bang rewrite. A practical order: (1) move main.go to di.NewApp with your chosen adapter, (2) group existing routes into controllers implementing RegisterRoutes(r core.Router), (3) replace manual param/body parsing with typed extractors like core.PInt64("id") and core.B[T](), (4) move auth checks into Guards and logging into Interceptors, (5) swap hand-rolled middleware for the built-ins. Each step compiles and runs on its own.

Does NestGo support Server-Sent Events and WebSockets?

SSE is first-class: create a channel with core.NewSSEStream(n), send core.SSEEvent values from a goroutine, and return core.SSE(c, stream) from the handler — see Server-Sent Events. WebSockets are adapter-specific: NestGo detects upgrade requests with core.IsWebSocketRequest, and you perform the upgrade through c.Underlying() using your adapter’s WebSocket library. There is no framework-level WebSocket gateway abstraction like NestJS’s — that trade-off is covered honestly in NestGo vs NestJS.

Next steps