Description
📝 Bug Description
When using graceful shutdown with Fiber, if there's a long-running request in progress (e.g. a database query), the request's context.Context
is immediately canceled once app.Shutdown()
is called. This leads to the request failing with a 500 Internal Server Error
with error failed to get user: context canceled
, even though the user initiated the request before the shutdown started.
This behavior creates a poor user experience, especially in production environments where graceful termination of active connections is expected. 🙁
🔁 How to Reproduce
- Start a Fiber app with a handler that simulates a slow operation (e.g. sleep + DB call).
- Send a request to that handler.
- While the request is still processing, trigger a graceful shutdown via
app.Shutdown()
. - Observe that the request fails with a 500 due to context cancellation with this error
failed to get user: context canceled
.
Here is a simple example
func main() {
app := fiber.New(fiber.Config{
ReadTimeout: time.Second * 30,
WriteTimeout: time.Second * 20,
})
app.Get("/", func(c *fiber.Ctx) error {
// Simulate a long-running request
time.Sleep(time.Second * 10)
// This DB call will fail if context is canceled
user, err := getUser(c.Context())
if err != nil {
return err // results in 500 if shutdown started
}
return c.JSON(user)
})
go func() {
if err := app.Listen(":8080"); err != nil {
log.Panic(err)
}
}()
// Wait for interrupt signal
c := make(chan os.Signal, 1)
signal.Notify(c, os.Interrupt, syscall.SIGTERM)
<-c
fmt.Println("Gracefully shutting down...")
_ = app.Shutdown() // This cancels the context of in-flight requests
fmt.Println("Cleanup done.")
}
// getUser simulates a DB query that respects context
func getUser(ctx context.Context) (*models.User, error) {
var user models.User
if err := db.GetContext(ctx, &user, `SELECT * FROM users LIMIT 1`); err != nil {
return nil, fmt.Errorf("failed to get user: %w", err)
}
return &user, nil
}
💥 Expected Behavior
- Ongoing requests should be allowed to complete before shutdown fully proceeds.
- Context should not be canceled immediately upon calling
Shutdown()
if the request is already in progress.
✅ Suggested Fix
It would be great if Fiber could delay context cancellation for in-flight requests or provide a mechanism to wait for active requests to finish before finalizing the shutdown process. This would better align with typical graceful shutdown behavior seen in other Go HTTP frameworks.
Fiber Version
v2.52.6
Checklist:
- I agree to follow Fiber's Code of Conduct.
- I have checked for existing issues that describe my problem prior to opening this one.
- I understand that improperly formatted bug reports may be closed without explanation.