Mahamudul Hasan Rubel
HomeAboutProjectsSkillsExperienceBlogPhotosContact
Mahamudul Hasan Rubel

Senior Software Engineer crafting high-performance web applications and SaaS platforms.

Navigation

  • Home
  • About
  • Projects
  • Skills
  • Experience
  • Blog
  • Photos
  • Contact

Get in Touch

Available for senior/lead roles and consulting.

bd.mhrubel@gmail.comHire Me

© 2026 Mahamudul Hasan Rubel. All rights reserved.

Built with using Next.js 16 & Tailwind v4

Back to Blog
WordPressJune 24, 20264 min read

WordPress rewrite rules: Deconstructing the flush_rewrite_rules process

Learn how WordPress rewrite rules work under the hood. Discover why calling flush_rewrite_rules too often causes performance issues and how to manage it.

WordPressPerformanceWP_RewriteDeveloper TipsBackendTutorial

I remember sitting on a support call about three years ago, watching a site’s TTFB climb to nearly two seconds every time an administrator saved a post. It turned out the developer had placed a flush_rewrite_rules() call directly inside a save_post hook. It was a classic mistake: they were essentially rebuilding the entire URL routing table on every single update, causing a massive I/O bottleneck.

If you’re working with custom post types or complex routing, you’ve likely bumped into the WordPress Rewrite API. Understanding how flush_rewrite_rules updates the database and .htaccess is the difference between a snappy site and one that hangs every time a user hits "Update."

Understanding the WordPress rewrite rules lifecycle

When a user visits a URL, WordPress doesn't just "know" where the content lives. It uses a complex set of regular expressions to map that URL to a query. These rules are stored in your database under the rewrite_rules option key.

When you call flush_rewrite_rules(), WordPress performs a heavy lifting operation:

  1. It iterates through all registered rewrite rules (from core, plugins, and your theme).
  2. It compiles these rules into a massive serialized array.
  3. It saves this array to the wp_options table.
  4. It triggers a call to save_mod_rewrite_rules() to update the .htaccess file if you're on Apache.

This isn't a lightweight operation. In my experience, on a site with around 500 custom rules, this process can add roughly 200ms to a page load. If you’re doing this on every page view or every post save, you’re hitting the disk and the database hard for no reason.

The .htaccess generation trap

The .htaccess generation part is where things get tricky. WordPress uses the WP_Rewrite class to generate the rewrite block. If you're on a server where the filesystem is slow or locked, this call can trigger a race condition or a timeout.

We once tried to automate a custom routing system by flushing rules every time a user changed a site setting. It worked for a week until the traffic spiked. The site started throwing 500 errors because the WP_Rewrite object was trying to write to the file system while simultaneously being accessed by hundreds of concurrent requests. We eventually had to move the flush logic to a dedicated CLI command.

If you want to master the full scope of how these requests map to content, check out my guide on the WordPress Rewrite API: How URL Requests Map to Content.

When to actually flush

You only need to flush when the routing structure changes. This happens when:

  • You register a new Custom Post Type (CPT) or Taxonomy.
  • You change the permalink structure settings.
  • You programmatically add a new rewrite rule via add_rewrite_rule().

You do not need to flush just because you updated a post or changed a meta field. If you’re struggling with rules not showing up, you might want to review WordPress Rewrite API: Managing Rules and Flush Failures to see if your registration logic is firing at the right time.

A better approach to flushing

Instead of calling the function blindly, check if you actually need to. You can hook into the activation of your plugin to flush once, rather than on every hook:

PHP
register_activation_hook( __FILE__, 'my_plugin_activation' );

function my_plugin_activation() {
    #6A9955">// Register your CPTs here
    my_custom_post_type_registration();
    
    #6A9955">// Flush only on activation
    flush_rewrite_rules();
}

If you must flush dynamically, use a transient or an option to check if a flush is actually required. Don't let the code run blindly.

FAQ: Common hurdles

Q: Does flush_rewrite_rules() always update .htaccess? A: Only if the filesystem is writable and the site uses Apache. On Nginx, WordPress can't write to the config file, so it relies entirely on the database-stored rewrite rules.

Q: Is it safe to call this in the admin_init hook? A: No. admin_init fires on every admin page load. You will be flushing the rules thousands of times a day, which is a major performance killer.

Q: What if I have thousands of custom rules? A: If you have thousands of rules, the rewrite_rules option in the database will grow huge, slowing down every single page load because WordPress autoloads that option. In that case, you should look into using add_rewrite_endpoint() or a custom query var approach to reduce the rule count.

I’m still experimenting with caching the rewrite_rules array in Redis to see if I can bypass the database hit entirely on high-traffic installs. It’s a bit experimental, but for sites with massive rule sets, the standard WP_Rewrite process just isn't built for that kind of scale. Always test your flush logic in a staging environment before pushing to production—you don't want to be the one who breaks the routing for the entire site.

Back to Blog

Similar Posts

WordPressJune 23, 20264 min read

WordPress Rewrite API: Managing Rules and Flush Failures

Master the WordPress Rewrite API and learn why calling flush_rewrite_rules incorrectly ruins performance. Get expert tips on managing WordPress permalinks.

Read more
WordPressJune 24, 20264 min read

WordPress rewrite rules: How Regex Patterns Generate from Permalinks

WordPress rewrite rules dictate how your site maps URLs to content. Learn how the WP_Rewrite engine transforms permalinks into regex for efficient routing.

Read more
WordPressJune 24, 20264 min read

WordPress URL rewriting: How parse_request maps your site permalinks

WordPress URL rewriting relies on the parse_request hook. Learn how the core routing engine converts permalinks into query variables to fetch your content.

Read more