Cache Control Headers
The Gothic Framework provides a built-in pluggable cache system that handles page and API response caching with multiple strategy options. You configure the cache in the Runtime block of your gothic.config.go file, which sets the cache strategy and static file serving. The runtime Middleware then applies that configuration, and RegisterFileBasedRoutes wires up your file-based routes.
CACHE_CONTROL_HEADERS is the default strategy. It does not store cached data in your application. Instead, it sets Cache-Control headers on responses so that a CDN (like AWS CloudFront) caches them at the edge. This is the recommended strategy for AWS deployments with the Gothic deploy tool.
The runtime Middleware reads the GOTHIC_MODE environment variable. Set GOTHIC_MODE=dev in your .env file for local development. When absent or set to any other value, the application runs in production mode.
Security Note: Error responses (status ≥ 300) are not cached under any strategy — they pass through to the client without being stored or served from cache. The Middleware function on any route type can end the request before the page renders by writing a redirect or error status. When the middleware produces a non-2xx response, the page rendering is skipped and nothing enters the cache.
Here is a typical gothic.config.go using Cache Control Headers:
package main
import gothic "github.com/gothicframework/core/config"
var Config = gothic.Config{
ProjectName: "my-project",
Runtime: gothic.RuntimeConfig{
CacheStrategy: gothic.CACHE_CONTROL_HEADERS,
LocalDevelopmentCache: gothic.IN_MEMORY,
ServeStaticFiles: gothic.CDN,
},
}And here is the main.go that applies it with the runtime Middleware:
package main
import (
"log"
"log/slog"
"net/http"
"os"
"your-module/src/routes"
gothicServer "github.com/gothicframework/middlewares"
"github.com/go-chi/chi/middleware"
"github.com/go-chi/chi/v5"
"github.com/joho/godotenv"
)
func main() {
godotenv.Load()
router := chi.NewMux()
router.Use(middleware.Logger)
router.Use(gothicServer.Middleware(Config.Runtime))
routes.RegisterFileBasedRoutes(router)
port := os.Getenv("HTTP_LISTEN_ADDR")
slog.Info("application running", "port", port)
log.Fatal(http.ListenAndServe(port, router))
}ServeStaticFiles controls when /public/* files are served from disk. CDN (default) serves them from disk only in dev mode and expects your production asset delivery layer to serve them. Gothic's native AWS deployment, for example, uses CloudFront and S3. Use DISK when the public folder ships alongside the binary.
EMBEDDED goes one step further: it bakes ./public into the server binary at build time via go:embed and serves /public/* straight from that embed in non-dev envs. The result is a single self-contained binary with no sidecar public/ folder — ideal for self-hosted containers and VMs. Prefer CDN when your deployment provider serves assets through an external CDN or object store. On Gothic's native AWS deployment, for example, gothic deploy warns when EMBEDDED is selected because assets are delivered separately. In dev mode (GOTHIC_MODE=dev) files are always served fresh from disk regardless of the mode.
package main
import gothic "github.com/gothicframework/core/config"
var Config = gothic.Config{
ProjectName: "my-project",
Runtime: gothic.RuntimeConfig{
// Bake ./public into the server binary via //go:embed and serve
// /public/* from that embed in non-dev envs.
ServeStaticFiles: gothic.EMBEDDED,
},
}Want to cache pages directly in your application without a CDN? Check out the In Memory cache strategy!
