Reference guide · http-status · Published 2026-08-16 · 4 min read
HTTP 308 permanent redirect
HTTP 308 permanent redirect: the method-preserving permanent status, when to choose it over 301, and how to configure it safely.
- ·What 308 guarantees
- ·308 vs 301 vs 307
- ·When to use it
HTTP 308 Permanent Redirect tells the client: this URL moved for good, and the method stays the same. It is the permanent sibling of 307 in the same way 301 is the permanent sibling of 302: same "keep the method" rule, but the 308 is permanent while 307 is temporary. You will mostly meet it in API gateway configs, app frameworks, and rare cases of moving an endpoint that must keep a POST body.
What 308 means
- The location changed permanently. The search-engine and browser cache it like a 301, following it on later visits without asking.
- The method and body are preserved. Where a
301must not be trusted with aPOSTbody (browsers historically turned it into aGET), a308promises to re-send the same request to the new location with the same method and headers. - The cache follows it. After a 308 is cached, a subsequent request for the old URL goes straight to the new one, including its method, which is the promise front-end routers rely on.
Why browsers care
The familiar forms use POST: login, payment, and uploads. A plain 301 on a POST is dangerous because the browser can drop the body and reissue a GET to the new URL, losing the data entirely. 308 keeps the exact method for these:
| Redirect | Meaning | Method for POST | Cache |
|---|---|---|---|
| 301 | Moved permanently | Becomes GET (per specs, but body not kept) | Yes |
| 302 | Found (temporary) | Becomes GET | Usually no |
| 307 | Temporary redirect | Keeps POST | Usually no |
| 308 | Permanent redirect | Keeps POST | Yes |
When to use it
- Moving a webapp from one path to another (e.g. an install moves to a subfolder) where some traffic still submits
POSTto the old path a browser could have bookmarked. - An API endpoint that permanently moved. Use a
308for a request that must keep its verb and body, such as a rate-limited upload or a jobPOST. - Migrating between domains where forms could be hit on the old host. A 301 only reassures search; a 308 re-sends the data.
Do not use 308 when you need your real cache to rewrite a leading-slash form or when the old path should stop being followed: those are the cases for a 404 or 410, as in the 410 gone article.
Setup
# nginx
location /old-app/ {
return 308 https://new.example.com/app$request_uri;
}
// express
app.all('/old-app/*', (req, res) => {
res.status(308).redirect('https://new.example.com/app' + req.originalUrl);
});
Verify a submitted form keeps its body:
curl -i -X POST -d "name=jane" https://example.com/old-app/order
HTTP/1.1 308 Permanent Redirect
location: https://new.example.com/app/order
The trap
A 308 caches. If you ship a 308 and then back out, visitors and search bars have the old mapping cached and can keep following the 308 to nowhere, exactly like a mistimed 301. Test in a private browser and clear the old cache before and after; then make the redirect permanent only once you are sure. And never loop a 308: one permanent redirect pointing at another permanent redirect is the same friction as the too many redirects loop, just with caching on both sides.
When to involve a professional
If you are planning to move a domain and need to keep in-flight payment or upload POST requests intact, that is a redirect-map and cache TTL decision, not a quick header change. Load the redirect map migration work before you flip the edge.