maintenance

package
v0.0.26 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 24, 2026 License: MIT Imports: 5 Imported by: 0

README

Maintenance Mode Middleware

What it does

Provides a runtime maintenance switch for controlled downtime, brownouts, migrations, deployments, and dependency outages.

It supports two production modes:

  • API mode: return a JSON maintenance response with 503 Service Unavailable.
  • Render/redirect mode: when Renderer and Path are configured, normal traffic redirects to the public maintenance path and that path is rendered by your custom handler.

How to implement

Basic JSON maintenance response
sw := maintenance.NewSwitch()
app.Use(maintenance.New(maintenance.Config{Switch: sw}))

sw.Enable("Database migration in progress")

During maintenance, requests receive:

HTTP/1.1 503 Service Unavailable
Retry-After: 60
Content-Type: application/json
Custom maintenance renderer

Renderer is a normal fh.Handler, so it can render HTML, JSON, templates, or static content using your existing response helpers.

sw := maintenance.NewSwitch()

app.Use(maintenance.New(maintenance.Config{
    Switch: sw,
    Renderer: func(c fh.Ctx) error {
        return c.Status(fh.StatusServiceUnavailable).
            Type("html").
            SendString(`<!doctype html><h1>Maintenance</h1><p>We will be back shortly.</p>`)
    },
}))
Redirect browser traffic to a maintenance page

When both Path and Renderer are configured, the middleware redirects non-bypassed requests to Path. Requests already targeting Path call the renderer directly, so redirect loops are avoided.

sw := maintenance.NewSwitch()

app.Use(maintenance.New(maintenance.Config{
    Switch: sw,
    Path:   "/maintenance",
    Renderer: func(c fh.Ctx) error {
        return c.Status(fh.StatusServiceUnavailable).
            Type("html").
            SendString(`<!doctype html><h1>We will be back soon</h1>`)
    },
    RedirectCode: fh.StatusFound,
}))
Bypass trusted internal traffic
app.Use(maintenance.New(maintenance.Config{
    Switch:       sw,
    BypassHeader: "X-Maintenance-Bypass",
    BypassToken:  "internal-secret",
}))

Configuration

type Config struct {
    Switch       *maintenance.Switch
    BypassHeader string
    BypassToken  string
    RetryAfter   time.Duration
    StatusCode   int

    Renderer     fh.Handler
    Path         string
    RedirectCode int

    JSONBody func(c fh.Ctx, data maintenance.ViewData) any
}

Impact

  • JSON mode returns 503 Service Unavailable by default.
  • Renderer mode uses your handler, so your handler controls status, content type, and body.
  • Redirect mode returns 302 Found by default for normal routes and renders the maintenance page at Path.
  • Retry-After is set before either JSON or rendered responses.

Ordering guidance

Run early so expensive application handlers are skipped during maintenance. Place after trusted proxy/real-IP middleware if bypass decisions depend on proxy-derived headers. Decide whether health/admin endpoints should be bypassed based on your deployment model.

Production considerations

  • Protect switch control with admin auth, IP allowlists, mTLS, or internal-only ops APIs.
  • Keep the renderer fast and dependency-light so the maintenance page still works during outages.
  • Prefer JSON mode for APIs and redirect/render mode for browser-facing apps.
  • Use bypass headers only between trusted internal systems.

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func New

func New(cfg Config) fh.HandlerFunc

Types

type Config

type Config struct {
	Switch       *Switch
	BypassHeader string
	BypassToken  string
	RetryAfter   time.Duration

	// StatusCode is used for direct maintenance responses. Default: 503.
	StatusCode int

	// Renderer allows custom maintenance page rendering. When Path is configured,
	// non-bypassed requests are redirected to Path and requests to Path are served
	// by Renderer to avoid redirect loops.
	Renderer fh.Handler

	// Path is the public maintenance page endpoint, for example "/maintenance".
	// When Path is configured with Renderer, non-bypassed requests are redirected
	// to this path instead of receiving JSON immediately. Requests to Path call the
	// configured Renderer directly.
	Path string

	// RedirectCode is used when Path and Renderer are configured. Default: 302.
	RedirectCode int
}

type Switch

type Switch struct {
	// contains filtered or unexported fields
}

func NewSwitch

func NewSwitch() *Switch

func (*Switch) Disable

func (s *Switch) Disable()

func (*Switch) Enable

func (s *Switch) Enable(msg ...string)

func (*Switch) Enabled

func (s *Switch) Enabled() bool

func (*Switch) Message

func (s *Switch) Message() string

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL