Skip to content

Changelog

Changelog

All notable changes to this project will be documented in this file.

The format is based on Keep a Changelog and this project adheres to Semantic Versioning.

[Unreleased]

[2.3.0] - 2026-11-13

Deprecated

  • jwt.ExtractClaimsFromJwt: use ExtractClaimsFromJWT.
  • middleware.ContextMiddleware: use middleware.RequestContext.
  • i18n.MWOption: use i18n.MiddlewareOption.

The old names keep working and will be removed in fibr v3.

Added

  • fibrtest: NewRedis(t) starts an in-memory Redis (miniredis) and returns it with a connected go-redis client, both closed at test end.
  • ws: WithLogger sets the logger for decode and backplane errors.
  • rediskit: Redis.Logger sets the logger for Subscribe background errors.
  • mailer: NewLogSenderWithLogger.

Changed

  • Error messages from config, jwt, slug, and bootstrap now start with the package name (for example slug: check uniqueness: …), like the rest of the library. Code that matches these errors by text needs updating; errors.Is / errors.As are unaffected.
  • Generator: generated apps import fibr packages under fibr* aliases (fibrmailer, fibrjobs, …) instead of the legacy fh* prefix.
  • outbox: the relay marks a whole batch as published with one UPDATE instead of one per event, and renews its lock by elapsed time (a third of the TTL) instead of before every event. A batch of 100 is about 5x faster, and about 19x faster with a lock. Progress is still recorded when the context is cancelled mid-batch. If the process dies mid-batch, the events already published in that batch are sent again (previously at most one); delivery was and remains at-least-once.

[2.2.0] - 2026-11-13

Changed

  • Requires Bun v1.3.0 (was v1.2.18). Bun 1.3 changed Limit and Offset to take int64 and Count to return int64, so fibr can only build against one side of that change. Upgrading fibr therefore moves your module to Bun 1.3 too: convert your own Limit(n) / Offset(n) arguments to int64 and expect int64 from Count. Apps generated by fibr new are updated accordingly.
  • The minimum Go version is now 1.26.10 (required by updated dependencies).
  • Other dependency updates: go-redis v9.23.0, minio-go v7.4.1, prometheus/client_golang v1.25.0, validator v10.30.6, go-mail v0.8.2, OpenTelemetry OTLP exporter v1.47.0, miniredis v2.40.0 (test-only).

[2.1.0] - 2026-11-13

Deprecated

  • sse: use Fiber's own github.com/gofiber/fiber/v3/middleware/sse, which adds heartbeats, Last-Event-ID, and disconnect detection. The package keeps working and will be removed in fibr v3.
  • reqctx: GetContext, SetLocal, and GetLocal. Fiber v3 covers them with c.Context() and the generic fiber.Locals. GetRequestID stays.

Added

  • slug: GenerateReadable returns the plain slug (my-title) when it is free and falls back to the suffixed form otherwise.
  • outbox: the Attempt model and outbox_attempts table (created by Migrate).

Fixed

  • bootstrap: a request whose handler panicked was missing from the request log and from the metrics. A second recover middleware inside them now turns the panic into a 500 that both record.
  • metrics: requests that matched no route were all counted under path="/", mixed with the real root route. They are now labeled path="unmatched".

Changed

  • outbox: WithMaxAttempts counts failed publishes in the outbox_attempts table instead of in memory, so the count survives restarts and is shared across replicas. Re-run outbox.Migrate after upgrading if you use WithMaxAttempts. Prune also clears counters of events that are no longer pending.
  • Generator: the realtime sample (fibr new --realtime) now uses Fiber's SSE middleware, and ends its stream when the server starts shutting down so an open stream does not hold up a graceful shutdown.

[2.0.1] - 2026-11-13

Fixed

  • sse: an SSE stream could crash the whole process. Handler runs the stream function after the route handler has returned, when Fiber v3 has already recycled the fiber.Ctx; using c there (for example c.RequestCtx().Done(), as the generated realtime sample does) dereferenced a nil pointer on a goroutine no recover middleware covers. Handler now keeps the context alive for the duration of the stream, and recovers and logs a panic in the stream function instead of letting it kill the server.
  • Generator: the sample CRUD model now requires name, so POST /<plural> with an empty body returns 422 instead of creating an empty record.

[2.0.0] - 2026-11-13

fibr v2 targets Fiber v3. See MIGRATING.md for upgrade steps. v1 (Fiber v2) continues on the v1 branch.

Changed

  • Breaking: the module path is now github.com/rahmadafandi/fibr/v2. Update imports and go get github.com/rahmadafandi/fibr/v2.
  • Breaking: fibr now targets Fiber v3 (github.com/gofiber/fiber/v3) instead of the deprecated Fiber v2. For code that uses fibr:
  • Handlers and middleware take fiber.Ctx (an interface) instead of *fiber.Ctx.
  • The request context is c.Context() (was c.UserContext()); ContextMiddleware sets it with c.SetContext.
  • Use c.Bind().Body/Query/URI instead of c.BodyParser/QueryParser/ParamsParser; path-parameter struct tags are uri:"…" instead of params:"…". The bind package does this for you.
  • bootstrap.Options.FiberConfig and Options.CORS are the Fiber v3 types; cors.Config.AllowOrigins is now a []string.
  • redis.Storage implements Fiber v3's fiber.Storage, including the new …WithContext methods.
  • Tracing uses github.com/gofiber/contrib/v3/otel and ws uses github.com/gofiber/contrib/v3/websocket.
  • Apps generated by fibr new are Fiber v3 apps.
  • Breaking: three packages are renamed so they no longer collide with the packages they are used alongside (no more import aliases): context → reqctx, http → httpclient, redis → rediskit. Only the package name and import path change; the APIs are the same.
  • Breaking: safer defaults.
  • uploader: files are stored as <random>-<name> by default, so same-named uploads never overwrite each other. WithUniqueNames is gone; use WithOriginalNames() to keep the original name (and the overwrite behavior).
  • uploader: Uploader.Upload takes a context.Context as its first argument. UploadContext and ContextUploader are removed.
  • auth: RequireAuth and Optional reject tokens without an exp claim. WithExpirationRequired is gone; use WithExpirationOptional() to accept non-expiring tokens.
  • bootstrap: Options.EnableCORS is removed; CORS is off unless you set Options.CORSOrigins (a list of allowed origins) or Options.CORS (full config). Nothing allows every origin implicitly any more.
  • Apps generated by fibr new read allowed origins from CORS_ALLOW_ORIGINS (comma-separated); CORS is off when it is unset.

[1.6.1] - 2026-11-13

Changed

  • Dependency updates: Fiber v2.52.15, go-redis v9.22.0, fasthttp v1.73.0, minio-go v7.3.0, go-mail v0.8.1, prometheus/client_golang v1.24.1, OpenTelemetry v1.46.0, validator v10.30.4, mimetype v1.4.16, fasthttp/websocket v1.5.12, and (test-only) testify v1.12.1 and miniredis v2.39.0.

[1.6.0] - 2026-11-12

Added

  • apierror: StatusOf(err) returns the HTTP status Handler responds with for an error.
  • uploader: WithUniqueNames() stores each file as <random>-<name> so same-named uploads cannot overwrite each other; UploadContext on both uploaders and the ContextUploader interface make uploads cancellable.
  • parser: MaxLimit (default 1000) caps the page size applied by Paginate and Keyset.
  • jwt: ErrEmptySecret.
  • auth: WithExpirationRequired() rejects tokens without an exp claim.
  • outbox: WithMaxAttempts(n) moves an event that keeps failing to the new outbox_dead table (DeadEvent) instead of blocking the queue; Prune deletes old published events; WithLogger sets the relay's logger.
  • inbox: Prune deletes old dedup markers.
  • ratelimit: New accepts options; WithLogger sets the logger used when Redis fails.
  • bootstrap: Options.CORS (*cors.Config) to restrict allowed origins.
  • Integration tests against real Postgres and Redis (make integration), run in CI.

Changed

  • parser: page sizes above MaxLimit are now clamped (previously unbounded). Set parser.MaxLimit = 0 to restore the old behavior.
  • jwt: GenerateToken, GenerateTokenWithExpiry, and ValidateToken return ErrEmptySecret for an empty secret. Consequently auth.RequireAuth("") rejects every request and an Issuer with an empty secret cannot issue tokens.
  • middleware: ContextMiddleware derives the request context from c.UserContext() and also stores it there, so c.UserContext() now carries the request timeout and request id. Handlers that pass c.UserContext() to slow calls are therefore bounded by the request timeout (bootstrap.Options.RequestTimeout, default 10s), as context.GetContext(c) callers already were.
  • bootstrap: the tracing middleware runs before ContextMiddleware, so the request context is a child of the request span.
  • outbox: Migrate also creates the outbox_dead table; with WithLock, the relay renews its lock before each event.
  • examples/.env is now examples/.env.example.

Security

  • Bumped golang.org/x/net (v0.60.0), golang.org/x/text (v0.42.0), klauspost/compress (v1.20.2), andybalholm/brotli (v1.2.7), OpenTelemetry (v1.45.0), and google.golang.org/grpc (v1.83.1), and the Go toolchain to 1.26.11, to pick up fixes for vulnerabilities reported by govulncheck.

Fixed

  • middleware: the request logger logged status: 200 for any error returned by a handler; it now logs the status the client receives.
  • metrics: *apierror.Error responses (e.g. a 404) were counted as status="500".
  • server: a zero Timeout made the shutdown context expire immediately, aborting shutdown and cleanup hooks; it now defaults to 10 seconds.
  • lock: Do did not release the lock when its context was cancelled while fn ran, leaving the key held until its TTL.
  • parser: search used ILIKE on every database and failed on SQLite; it now uses LIKE outside Postgres.

[1.5.0] - 2026-06-14

Added

  • retry package: generic retry with exponential backoff + optional jitter — Do(ctx, fn, opts...) and DoValue[T], with WithAttempts/WithDelay/WithMaxDelay/WithMultiplier/WithJitter/WithRetryIf.
  • inbox package: idempotent-consumer dedup — Once(ctx, db, messageID, fn) records a marker and runs fn in one transaction (duplicate IDs skip fn; a failing fn rolls the marker back). The consumer-side complement to outbox.
  • dbresolver package: explicit read/write split over Bun — New(primary, replicas...) with Writer() (primary) and Reader() (round-robin replica, primary when none), plus Ping/Close.

[1.4.0] - 2026-06-14

Added

  • pagination: (*CursorPage[T]).LinkHeader(baseURL) builds an RFC 5988 Link header with rel="next"/rel="prev" from the page cursors.
  • http: WithContextHeader(header, extract) sets a per-request header from the call's context (e.g. propagate a request id or trace correlation downstream).

[1.3.0] - 2026-06-14

Added

  • cache package: a generic in-memory cache Cache[V] with TTL, LRU max-size eviction, and singleflight GetOrLoad. Complements redis.Remember (remote) for hot data without a network round-trip.
  • ratelimit package: a Redis-backed token-bucket limiter (per-key buckets, cost-per-request via Allow) with a Fiber Middleware (429 + Retry-After + X-RateLimit-* headers).
  • apikey package: API-key authentication (distinct from JWT auth) — hash a presented key and resolve its identity + scopes via a pluggable Store (MapStore), with Generate/Hash, a Fiber Middleware, RequireScope, and FromContext/HasScope.

[1.2.0] - 2026-06-14

Added

  • health: dependency probes PingRedis, PingHTTP, and PingTCP.
  • health.ReadinessGate + server.RunGracefulWithConfig/server.Config: flip /readyz to not-ready and wait a drain delay before shutting down, so a load balancer stops routing first. server.RunGraceful is unchanged (delegates with the new defaults).
  • http: optional circuit breaker via WithCircuitBreaker(maxFailures, openTimeout) — rejects calls with ErrCircuitOpen while a dependency is failing, with a half-open probe after the timeout.
  • redis.Remember: in-process singleflight deduplication so concurrent misses for the same key run the loader once (cache-stampede protection).
  • events package: in-process typed event bus (Subscribe[T]/Publish[T]), synchronous by default with an opt-in async mode (WithAsync). Complements outbox for intra-process fan-out.
  • featureflag package: runtime flags (boolean, percentage rollout, per-user/group targeting) via a pluggable Provider — Static, Rules, and Redis — plus a Fiber Middleware and Enabled(c, flag) helper.
  • audit package: structured audit log — a Recorder writes actor/action/target entries through a pluggable Sink (NewBunSink + Migrate + List), with a Fiber FromRequest helper prefilling actor/IP/request-id.

[1.1.0] - 2026-06-13

Fixed

  • lock: Acquire now reports ErrNotAcquired when the context is cancelled or times out during an acquisition attempt (previously the raw Redis transport error could leak through, so errors.Is(err, ErrNotAcquired) was unreliable).

Added

  • lock package: single-instance Redis distributed mutex (TryAcquire/Acquire/Do, owner-only Release/Extend) for single-execution across replicas.
  • Keyset (cursor) pagination: parser.Keyset Bun modifier with opaque cursors (EncodeCursor/DecodeCursor) and pagination.CursorPage/NewCursorPage with forward and backward navigation. Complements the existing offset pagination.
  • outbox package: transactional outbox (Enqueue within a Bun transaction + a background Relay that publishes pending events at-least-once, with NewRedisPublisher and optional single-relay coordination via lock). Solves the dual-write problem between the database and Redis pub/sub.
  • fibrtest package: a test harness for fibr/Fiber apps — a fluent HTTP Client over *fiber.App (Get/Post/Request builder, WithBearer), response assertions (ExpectStatus/JSON/Text), plus NewDB (in-memory SQLite Bun) and Token (JWT minting) helpers.

[1.0.0] - 2026-06-13

First stable release. The public API is now covered by the compatibility guarantee in the README — no breaking changes will land within the v1.x series; anything breaking will go to v2.

No functional changes since v0.6.0. This release marks the API as stable after the v0.6.0 hardening pass (idiomatic-Go cleanup, stricter linters, fuzz tests for the parser surfaces, and the final breaking renames).

[0.6.0] - 2026-06-13

Added

  • redis: bulk and atomic helpers — MSet/MGet (pipelined), Incr/Decr, SetNX, GetSet.
  • http: PostForm (urlencoded) and PostMultipart (file upload) requests.
  • jobs: option helpers WithRetry/WithPriority/WithProcessIn/WithDeadline (return asynq.Option, so callers need not import asynq).
  • i18n: CLDR cardinal plural categories (zero/one/two/few/many/other) for en/fr/ru/uk/pl/ar and the no-plural languages; unknown locales use the English rule. Plural now resolves <key>.<category>.
  • ws: (*Hub[T]).BackplaneErr() surfaces a failed Redis backplane subscription (the hub still serves local connections).

Changed

  • Added // Package doc comments to 16 packages; replaced interface{} with any.
  • Stricter golangci-lint set (revive, unconvert, unparam, …) enforced in CI.

Removed

  • Breaking: http.Http renamed to http.HTTP and http.HTTPError to http.Error (stutter fixes). Update references accordingly.
  • Breaking: middleware.Auth removed — use auth.RequireAuth (adds token revocation and scope checks).

[0.5.0] - 2026-06-11

Added

  • openapi package: build an OpenAPI 3.0.3 spec from registered routes and reflected request/response structs (json + validator tags → JSON Schema with $refs, enums, formats, and min/max constraints). Serve it at /openapi.json with a CDN-backed Swagger UI at /docs. New bootstrap.Options.OpenAPI (plus OpenAPISpecURL/OpenAPIDocsURL) mounts both endpoints, and generated apps expose API docs out of the box (auth routes pre-registered when --auth).
  • ws package: typed WebSocket Hub[T] (rooms, Broadcast/ToRoom, per-connection write pump, keepalive ping) on gofiber/contrib/websocket, with an optional Redis backplane (WithRedis) bridging broadcasts across replicas via the existing redis pub/sub.
  • sse package: Server-Sent Events stream helper (Handler + Stream.Send/SendRaw/ Comment/Event) with JSON encoding and multi-line data framing.
  • Generator: new fibr new --realtime flag scaffolds a WebSocket chat (/ws/:room) + SSE counter (/events); backplane auto-enabled when REDIS_URL is set.
  • i18n package: dependency-free internationalization — a message Bundle loaded from nested JSON (flattened to dotted keys) with {placeholder} substitution, one/other pluralization (Plural/N), and a fallback locale; a locale-detection middleware (query > cookie > Accept-Language) and T/N/Locale request helpers. New bootstrap.Options.I18n mounts the middleware, and fibr new --i18n scaffolds en/id catalogs + a sample localized route.

[0.4.0] - 2026-06-10

Added

  • bind package: Body[T]/Query[T]/Params[T] parse a request into T, validate it, and on failure write a 400 (malformed) or 422 (validation, with per-field errors) response — returning ok=false so handlers stop with return nil.
  • jobs.Scheduler: cron-triggered job scheduling (Register/Run/Shutdown/Unregister, WithLocation) on top of asynq. Generated --queue apps gain a scheduler subcommand and a sample daily cleanup cron.
  • uploader.S3Uploader: S3-compatible uploads (AWS S3, MinIO, R2, ...) via minio-go, behind the existing Uploader interface, with WithKeyPrefix / WithBaseURL. Validation (size, MIME, filename) is now shared with LocalUploader; the Option type is unified across both.
  • redis.Storage (NewStorage/WithPrefix): a fiber.Storage adapter over go-redis, plus bootstrap.Options.RateLimitStorage. Generated apps use a Redis-backed (multi-instance-consistent) rate limiter when REDIS_URL is set.

  • apierror package: typed HTTP errors (BadRequest/Unauthorized/NotFound/ Conflict/Internal/...) with WithCode/WithDetails/Wrap, plus a Fiber ErrorHandler. bootstrap installs it by default, so a returned error renders as the JSON envelope. Adds an optional error field to response.Response. Generated auth handlers now return typed errors.

  • bootstrap.Options.SecurityHeaders (helmet security response headers) and Compression (gzip/deflate/brotli) opt-in middlewares; generated apps enable both by default.

  • bootstrap.Options.Idempotency + IdempotencyStorage: opt-in idempotency-key middleware (replays the cached response for a repeated X-Idempotency-Key on unsafe methods). Generated apps enable it, backed by Redis when REDIS_URL is set.
  • webhook package: HMAC-SHA256 Sign/Verify (Stripe-style t=,v1= with timestamp replay protection) and a Middleware that guards inbound webhook routes (401 on bad signature).
  • redis pub/sub: (*Redis).Publish and generic Subscribe[T] (background goroutine + Subscription.Close) for cross-instance events like cache invalidation and broadcasts.

Changed

  • Generated handlers (module CRUD + auth register/login/refresh) now use bind.Body and validate input via struct tags. Missing required fields now return 422 instead of 400.

[0.3.0] - 2026-06-08

Changed

  • BREAKING: renamed the project from fiber-helpers to fibr. The module path is now github.com/rahmadafandi/fibr; update all imports. The repository moved to github.com/rahmadafandi/fibr (the old URL redirects).
  • BREAKING: the generator CLI is now fibr with subcommands. Scaffold a project with fibr new <name> (was create-fiber-app <name>); fibr add module <name> is unchanged. Install with go install github.com/rahmadafandi/fibr/cmd/fibr@latest. Release binaries are named fibr.

[0.2.2] - 2026-06-08

Added

  • Developer tooling: root Makefile (build/test/cover/lint/vet/vuln/tidy/check), lefthook.yml git hooks (gofmt + golangci-lint on commit, tests on push).
  • CI: govulncheck vulnerability scan job; test coverage profile uploaded to Codecov; examples build/vet job.
  • Documentation: runnable godoc Example functions for pagination, jwt, validator, parser, response, and slug (rendered on pkg.go.dev).
  • examples/: runnable demo apps for auth, mailer, and queue, plus a README index.

[0.2.1] - 2026-06-08

Changed

  • go.mod: retract pre-release tags [v0.1.0, v0.1.13]. They predate the project stabilizing and point at commits removed by a history rewrite; they were never intended as supported releases. go get and pkg.go.dev now steer users to v0.2.0+.

[0.2.0] - 2026-06-07

Added

  • metrics package: Prometheus request metrics middleware + /metrics handler (http_requests_total / http_request_duration_seconds with route-template labels; default Go/process collectors). Opt-in via bootstrap.Options.Metrics; generated apps toggle it with METRICS_ENABLED.
  • tracing package: OpenTelemetry tracer setup (Setup with OTLP/HTTP exporter, global provider + W3C propagator, WithServiceName/WithSampler). Opt-in via bootstrap.Options.Tracing (otelfiber spans) + Options.Cleanup; request logs gain trace_id/span_id; generated apps toggle with TRACING_ENABLED.
  • database.WithTracing(): installs Bun's bunotel OpenTelemetry query hook so SQL queries are recorded as spans. Generated apps enable it automatically when TRACING_ENABLED is set.
  • redis cache helpers: Delete (variadic), Exists, Expire, and TTL on *Redis for invalidating and inspecting cached entries.
  • jobs package: typed asynq queue wrapper (Client.Enqueue, generic Handle[T], worker Server with Run/ProcessTask) and a mountable asynqmon monitoring handler (MonitoringHandler).
  • bootstrap.Options.Asynqmon (AsynqmonMount): opt-in mount for a monitoring UI http.Handler with optional guard middleware (asynqmon dependency stays out of bootstrap).
  • create-fiber-app --queue: scaffolds a sample job, a worker subcommand, the asynqmon UI mount, and REDIS_URL/QUEUE_CONCURRENCY/ASYNQMON_PATH config (both ddd and layered layouts). Empty REDIS_URL disables the queue with a warning (fail-soft).
  • mailer package: pluggable Sender (SMTPSender via go-mail, LogSender dev fallback, MemorySender for tests), Message, and a Render HTML+text template helper. New falls back to LogSender when no SMTP host is set.
  • create-fiber-app --mailer: scaffolds SMTP config/env, a /email/test route, and real send wiring for the welcome job (--queue, async via an email:send job) and team invitation email (--auth-with-team). Both layouts.
  • auth package: bcrypt Hash/Compare, JWT bearer middleware (RequireAuth/Optional), claims accessors (Claims/Subject), and scope checks (RequireScope/HasScope/Scopes).
  • auth refresh tokens + revocation: Issuer (Issue/Refresh/Logout) mints rotating access+refresh JWT pairs (TokenPair) with family-based reuse detection; TokenStore interface with RedisStore and MemoryStore impls; WithBlocklist makes RequireAuth/Optional reject revoked tokens by jti (refresh tokens are also rejected for API access).
  • create-fiber-app --auth: scaffolds an auth module (Account, register/login/me
  • scope-gated route, accounts migration) and generates a random JWT_SECRET. Login returns an access+refresh TokenPair; adds /auth/refresh and /auth/logout; wires a redis-backed token store when REDIS_URL is set, falling back to an in-memory store otherwise.
  • auth team/workspace helpers: ActiveTeam, TeamRole, RequireTeam, and RequireRole read the active team carried in the JWT (team/role claims); the Issuer now propagates team/role through refresh.
  • create-fiber-app --auth-with-team (implies --auth): multi-tenant scaffold where one account belongs to many teams via memberships, each team role maps to a permission set (carried as the active team's scopes). Adds Team/Membership entities + migrations, POST /auth/switch-team, GET /teams, POST /teams, POST /teams/:id/members (gated by member:manage), team-aware /me, and a team:manage example route; register auto-creates a personal team.
  • create-fiber-app --auth-with-team dynamic roles: each team owns its roles in the database (roles + role_permissions tables, seeded with owner/admin/member/viewer on team creation) instead of a static code map. Permissions are drawn from a fixed code catalog (GET /permissions) and resolved into the JWT at login/switch-team. Adds role management — GET/POST /teams/:id/roles, PUT/DELETE /teams/:id/roles/:name (owner- protected, in-use 409), and PUT /teams/:id/members (change a member's role) — all gated by role:manage/member:manage and scoped to the active team.
  • migrate package: bun/migrate wrapper (Up/Down/Status/Create) plus a ready cobra NewCommand (up/down/status/create).
  • Generated projects are now a single cobra binary with serve + migrate subcommands and an internal/migrations/ package; --sample and add module emit create table migrations.
  • bootstrap.Options.AutoMigrate to run module Migrate at startup (dev).
  • bootstrap.Module interface and App.Mount for self-wiring feature modules, with optional Migrator and HealthChecker capabilities.
  • health.RegisterProvider / RegisterProviderAt for live readiness checks.
  • create-fiber-app add module <name> subcommand scaffolding a complete feature module for the detected layout (ddd/layered).
  • database: NewBun opens a Bun ORM connection with automatic Postgres/SQLite dialect detection from the DSN; pool options (WithMaxOpenConns, WithMaxIdleConns, WithConnMaxLifetime, WithPingTimeout, WithoutPing).
  • health: Register/RegisterAt mount /livez (liveness) and /readyz (readiness) endpoints that run named checks concurrently; /readyz applies an overall deadline so a stuck check cannot hang the server. PingBun and Check helpers provided.
  • server: RunGraceful starts a Fiber app and blocks until SIGINT/SIGTERM, then shuts the server down cleanly and calls optional cleanup hooks.
  • bootstrap: New(Options) wires recover, request-id, structured logging, optional CORS, optional rate limiting (health probes are exempt), optional DB health checks, and graceful shutdown in a single call. App.Run(addr) replaces fiber.App.Listen.
  • config: default:"..." and required:"true" struct tags; extended type support (time.Duration, float, bool, integer with per-kind overflow detection, comma-separated []string); combined error reporting across all fields.
  • http: Context-aware JSON client built on fasthttp. All methods (Get, Post, Put, Patch, Delete) accept context.Context and return (statusCode int, err error). WithRetry retries only on 5xx; WithTimeout, WithHeader options; FireAndForget for background non-blocking calls; HTTPError type for status-code errors.
  • redis: Generic Remember cache-aside helper that returns a cached value or calls a loader on miss. ParseRedisOptions parses a Redis URL into *redis.Options and returns an error on bad input.
  • validator: Register for custom validation rules; error messages use JSON field names and include the failing value; handles non-struct input without panicking.
  • jwt: GenerateTokenWithExpiry for generating tokens with an explicit expiry duration.
  • uploader: WithMaxSize and WithAllowedMime options for NewLocalUploader; filenames are sanitized and permissions are tightened; partial files are removed on write error.
  • middleware: X-Request-ID response header added by the request-id middleware so callers can correlate responses.
  • context: SetLocal and GetLocal typed helpers replace the former CustomContext.
  • pagination: pagination package extracted to manage page/limit logic independently.

Changed

  • bootstrap.App.Mount runs a module's Migrate only when the app was built with AutoMigrate: true (previously always). Schema is owned by migrations by default.
  • create-fiber-app --sample now generates the sample user feature as a bootstrap.Module mounted via app.Mount (previously hand-wired in main.go).
  • ORM migration: GORM removed; Bun is now the ORM throughout the library. parser pagination scopes and slug.Generate (now slug.Generate(ctx, db, table, text) (string, error)) migrated accordingly.
  • config.LoadConfig: Signature changed from a generic return (LoadConfig[T]() (T, error)) to pointer-out (LoadConfig(out any) error), matching idiomatic Go.
  • http methods: All request methods now accept a leading context.Context argument and return (int, error) instead of a plain error.
  • common package removed: Functionality split into the response and logger packages.

Removed

  • common package: Replaced by dedicated response and logger packages.
  • parser.ParseBody / ParseQuery / ParseParams: Removed generic parse helpers; use Fiber's built-in c.BodyParser, c.QueryParser, and c.ParamsParser directly.
  • redis.GormResult: Removed broken GORM-coupled helper; use Remember instead.

Fixed

  • pagination: Guard against divide-by-zero when limit is zero; clamp page number to a valid range.
  • parser: Corrected ILIKE pattern construction; added SQL-injection guard on the sort column expression.
  • uploader: Path-traversal protection on uploaded filenames; partial file is cleaned up on write error; file permissions tightened.
  • validator: No longer panics on non-struct input.
  • config: Per-kind numeric overflow detection; errors from all fields are combined and reported together.
  • slug: Uniqueness retry loop is now capped to prevent an infinite spin.
  • redis: ParseRedisOptions returns an error instead of nil on a bad URL.
  • server: Signal-notify goroutine and exit bridge goroutine are cleaned up correctly on return.
  • database: Malformed DSN schemes are rejected with an error instead of being silently treated as SQLite.
  • http: FireAndForget detaches from the caller's context so cancellation does not abort background requests; retry backoff is context-aware.