The homepage loads; every other URL returns 404. This is not a content problem — WordPress never saw the request. The rewrite layer that maps pretty URLs to PHP is missing, and the fix is usually one minute.
The 60-second fix
Settings → Permalinks → click Save (nothing needs to change — saving rewrites the rules). Or with WP-CLI: wp rewrite flush --allow-root. Reload any interior page.
It works because “saving” regenerates the rewrite rules WordPress stores for mapping /my-post/ to index.php?p=123. Those rules vanish when: a migration replaces the database, the .htaccess/web config is overwritten, or the site moves servers with a different URL structure.
Apache sites: check .htaccess
If flushing does not fix it, the file that executes the rules may be gone. Apache reads .htaccess in the site root; it must contain WordPress’s block (the permalink save screen offers to write it if the file is writable). Missing or empty .htaccess = rules exist in the DB but never execute.
nginx sites: server config, not WordPress
nginx ignores .htaccess entirely — rewrites live in the server block. The required piece is the catch-all that sends unmatched URLs to WordPress:
location / { try_files $uri $uri/ /index.php?$args; }
If your host’s nginx config lacks it (common after server migrations or panel rebuilds), flushing from WordPress changes nothing — the config must be fixed server-side. BT panel and most managed hosts include it by default; custom nginx builds often do not.
The migration variant
After moving a site, 404s often come with wrong URLs inside content (old domain). That is the search-replace job, not rewrites: wp search-replace "https://old.com" "https://new.com" --allow-root. The full post-migration checklist lives in the migration guide.
Still 404 after all that?
Two rarer causes: a security plugin hijacking routes (deactivate and test), and — on multisite — missing subsite rewrite handling. The free audit catches the config-level causes during its infrastructure review.
WordPress lost its rewrite rules — the mapping from pretty URLs to PHP. Save the Permalinks settings or run wp rewrite flush; the rules regenerate in one step. On nginx, rules live in server config, not WordPress — the try_files catch-all must exist in the nginx server block. On Apache, a missing or empty .htaccess has the same effect. Moving the database or server can drop stored rewrite rules and leave old-domain URLs in content. Flush permalinks and run wp search-replace for the domain swap. WordPress's standard rewrite block — visible in Settings → Permalinks when the file is writable. It routes all non-file requests to index.php so WordPress can resolve them.Why do all my WordPress pages 404 except the homepage?
Why did flushing permalinks not fix my 404s?
How does a migration break permalinks?
What should .htaccess contain for WordPress?