SiteError.comYour friendly guide to HTTP status codes
Status CodesBlog
  1. Home
  2. Blog
  3. Understanding HTTP 410 Gone: The Deliberate Tombstone, and Why It Beats 404 for Deletions

Understanding HTTP 410 Gone: The Deliberate Tombstone, and Why It Beats 404 for Deletions

August 3, 202610 min read
4xxClient Error

410 Gone is the status code for "this used to be here, we removed it on purpose, and it isn't coming back." Most sites never bother with it — everything that isn't found just returns 404, permanent or not — but 410 exists specifically to say something 404 can't: that the absence is intentional and final, not a mystery. The catch is knowing when you're actually entitled to say that, because the RFC is explicit that 410 is for certainty, not a guess. This post covers what 410 actually promises, how it differs from 404 and 451, when you've earned the right to use it, and how to return it correctly so crawlers and caches purge the URL faster than a plain 404 ever would.

What Is a 410?

A 410 tells the client that the resource used to exist at this URL, it's gone now, and the server believes — with confidence — that it's gone for good.

The 410 (Gone) status code indicates that access to the target resource is no longer available at the origin server and that this condition is likely to be permanent. If the origin server does not know, or has no facility to determine, whether or not the condition is permanent, the status code 404 (Not Found) ought to be used instead. — RFC 9110, Section 15.5.11

In plain English: 410 is a tombstone, not a shrug. Unlike 404, it explicitly tells clients "don't bother looking for this again — it's gone for good," which is exactly why the same RFC sentence contains its own guardrail: if you don't actually know whether the removal is permanent, you're supposed to use 404 instead. 410 is a claim about certainty, and the spec expects you to have earned it.

Don't use 410 when you're not sure if the removal is permanent — use 404 instead. Use 410 for intentionally deleted resources (like removed user accounts, expired content, or deprecated API endpoints) to help clients clean up their caches and bookmarks.

The "Don't Guess" Rule

This is the part that separates 410 from every other 4xx code covered on this site: the RFC doesn't just define what 410 means, it defines when you're allowed to use it. Most status codes describe a server state; 410 describes a server state plus a confidence requirement.

In practice, that confidence usually comes from one place: you made the deletion happen. If your application code ran a DELETE FROM articles WHERE id = ? or flipped a retired_at flag, you know for certain the resource is gone and isn't coming back by accident — that's a 410. If a request just doesn't match any route or record, and you have no way of knowing whether it never existed, existed and was removed, or is a stale link to something that moved, that's a 404 — the honest "no information" answer.

The practical test: can you point to the specific action that removed this, and are you confident nobody's bringing it back? If yes, 410. If you're inferring "well, it's not in the database, so I guess it's gone," that's still a 404 — you don't actually know the difference between "deleted" and "never existed" or "temporarily missing due to a bug."

410 vs 404 vs 451

Three codes cover different flavors of "you can't have this URL," and the difference is about what the server knows and why:

CodeMeaningUse when
404 Not FoundUnknown status — might never have existed, might be gone, server isn't sayingDefault case; you don't have (or don't want to reveal) certainty about permanence
410 GoneConfirmed permanent removalYou know the resource existed and was deliberately, permanently removed
451 Unavailable For Legal ReasonsBlocked by legal demandContent is withheld specifically because of a court order, DMCA notice, or government demand — not a routine deletion

410 and 404 are the pair that actually gets confused in practice — 451 is rare enough that it's usually an obvious, deliberate choice once it applies. The 404/410 line comes down entirely to certainty: 404 is the resource's status when the server won't or can't commit to "permanent," and 410 is the same absence with that commitment made explicit. You can compare 404 vs 410 side by side, including how each is treated by crawlers.

When to Use 410

The legitimate cases all share the same shape: something existed, you removed it on purpose, and you want that fact recorded:

  1. The resource was intentionally and permanently deleted — a user account closure, a retired product listing, a post the author explicitly took down.
  2. You want to inform clients to remove their references and links — 410 is a signal to well-behaved clients (and search engines) to stop holding onto bookmarks, cached copies, and inbound links to this URL.
  3. You want a stronger signal than 404 to purge caches — 410 tells intermediary caches this entry should be dropped, not just treated as temporarily unreachable.
  4. You're retiring an API endpoint for good — a deprecated /api/v1/* route that's been fully decommissioned, as opposed to one that's just temporarily down.

And the one rule that undoes all of the above: if you're not sure the removal is permanent, use 404 instead. A 410 you have to walk back — because the content actually comes back, or because the "deletion" was really a temporary outage — costs you more than an honest 404 would have, since caches and crawlers acted on your certainty.

Returning 410 Correctly

Express / Node.js

app.get("/products/:id", async (req, res) => {
  const product = await db.findProductIncludingDeleted(req.params.id);
 
  if (!product) {
    // No record of it ever existing — we genuinely don't know
    return res.status(404).json({ error: "not_found" });
  }
 
  if (product.deletedAt) {
    // We know it existed and we know we removed it — 410, not 404
    return res.status(410).json({
      error: "gone",
      message: "This product was permanently removed.",
    });
  }
 
  res.json(product);
});

The key move is keeping a tombstone (a soft-delete flag, a deletedAt timestamp, an audit log) instead of hard-deleting rows outright — you can't return a confident 410 for something you no longer have any record of removing.

Next.js App Router

// app/api/products/[id]/route.ts
export async function GET(
  request: Request,
  { params }: { params: Promise<{ id: string }> },
) {
  const { id } = await params;
  const product = await findProductIncludingDeleted(id);
 
  if (!product) {
    return Response.json({ error: "not_found" }, { status: 404 });
  }
 
  if (product.deletedAt) {
    return Response.json(
      { error: "gone", message: "This product was permanently removed." },
      { status: 410 },
    );
  }
 
  return Response.json(product);
}

Next.js doesn't ship a dedicated gone() helper the way it does notFound() and forbidden() for pages, so for App Router pages you'd throw or branch manually and render your own "this is gone for good" UI while returning the 410 from a Route Handler or middleware/proxy layer in front of it.

NGINX

# Explicitly retire a decommissioned path
location = /old-campaign {
    return 410;
}
 
# A whole family of deprecated API routes
location ~ ^/api/v1/ {
    return 410 '{"error":"gone","message":"API v1 has been retired. Use /api/v2."}';
    default_type application/json;
}

REST API JSON body

HTTP/1.1 410 Gone
Content-Type: application/json
 
{
  "error": "gone",
  "message": "This resource was permanently deleted on 2026-03-01 and will not return.",
  "documentation": "https://api.example.com/docs/errors#gone"
}

Unlike 204 and 304, a 410 response can and should carry a body — it's your chance to tell the caller why it's gone and where to look instead, rather than leaving them to guess.

410 and SEO

This is where 410 earns its keep over 404, and it's the main reason to bother with the distinction at all:

  • Indexing — 410 triggers faster removal from Google's index than 404. Google treats it as a definitive signal that the content is permanently gone, rather than something that might reappear.
  • Crawl behavior — crawlers quickly stop visiting URLs returning 410. It's a stronger "go away" signal than 404, which crawlers tend to keep periodically re-checking for longer.
  • Canonical signals — use 410 specifically when you want to explicitly tell search engines to remove a URL from their index faster than a 404 would get around to it.
  • Practical use — Google removes 410 URLs from the index more quickly than 404s, which makes 410 the right call for content takedowns, expired campaigns, or deleted user content you actively want gone from search results, not just quietly stale.

The tradeoff: that speed is exactly why the "don't guess" rule matters. A mistaken 410 gets a URL purged from the index faster than a mistaken 404 would — if you're wrong about the permanence, you've accelerated your own SEO damage.

Common Pitfalls

  1. Using 410 as a fancier 404. If you can't point to the specific deletion that caused the absence, you don't have the certainty 410 requires — use 404 and don't guess at permanence you can't back up.
  2. Hard-deleting records and losing the ability to return 410. Once a row is truly gone from your database with no trace, you can no longer distinguish "never existed" from "deleted" — soft-deletes or tombstone records are what make 410 possible.
  3. Leaving a 410 in place after content genuinely comes back. If a "permanently removed" resource is restored, update the response immediately — a stale 410 actively fights your own re-indexing efforts, since you told crawlers to stop checking.
  4. Sending an empty body on a 410. Unlike 204/304, 410 doesn't require an empty body — don't waste the opportunity to tell users and API consumers why the resource is gone and where to go next.
  5. Reaching for 410 to hide something instead of confirming it. 410 confirms the resource existed. If existence itself is sensitive, that's the 403-vs-404 privacy tradeoff, not a 410 situation — 410 is louder about "this was real," not quieter.

Wrapping Up

410 is the status code that rewards certainty. The rules of thumb:

  • 410 means confirmed, permanent removal — not "not found," and not a guess
  • If you're not sure the removal is permanent, the RFC itself says to use 404 instead
  • Keep tombstones (soft-deletes, deletedAt fields) so you can actually back up a 410 claim
  • Search engines purge 410s faster than 404s — a genuine advantage when you want a takedown to stick, and a genuine risk if you're wrong

For more, see our pages on 410 Gone, 404 Not Found, and 451 Unavailable for Legal Reasons. The broader "doesn't exist vs. won't disclose" story is covered in our understanding 404 Not Found post, and you can compare 404 vs 410 side by side.

Full Reference

410 Gone

The content has been permanently deleted from server, with no forwarding address.

Related Status Codes

🤨400Bad Request🔐401Unauthorized💳402Payment Required🚫403Forbidden🔍404Not Found🙅405Method Not Allowed🍽️406Not Acceptable🎫407Proxy Authentication Required⏰408Request Timeout⚔️409Conflict👻410Gone📏411Length Required❌412Precondition Failed📦413Payload Too Large📜414URI Too Long📼415Unsupported Media Type📖416Range Not Satisfiable😞417Expectation Failed🫖418I'm a Teapot🚪421Misdirected Request🤔422Unprocessable Entity🔒423Locked🎯424Failed Dependency⏰425Too Early⬆️426Upgrade Required🔑428Precondition Required🚦429Too Many Requests📋431Request Header Fields Too Large⚖️451Unavailable For Legal Reasons
Back to Blog

Popular Status Codes

  • 200 OK
  • 301 Moved Permanently
  • 302 Found
  • 400 Bad Request
  • 401 Unauthorized
  • 403 Forbidden
  • 404 Not Found
  • 500 Internal Server Error
  • 502 Bad Gateway
  • 503 Service Unavailable

Compare Codes

  • 401 vs 403
  • 301 vs 302
  • 404 vs 410
  • 500 vs 502
  • Compare any codes →

Categories

  • Informational
  • Success
  • Redirection
  • Client Error
  • Server Error
  • NGINX
  • Cloudflare
  • AWS ELB
  • Microsoft IIS

Tools

  • Cheat Sheet
  • Status Code Quiz
  • URL Checker
  • API Playground
  • Blog

© 2026 SiteError.com. All rights reserved.