Index: wp-includes/rewrite.php
===================================================================
--- wp-includes/rewrite.php	(revision 20781)
+++ wp-includes/rewrite.php	(working copy)
@@ -1927,19 +1927,42 @@
 	}
 
 	/**
+	 * Schedules a flush of the rewrite rules. 	
+	 *
+	 * @since 2.0.1
+	 * @access public
+	 * @param bool $hard Whether to update .htaccess (hard flush) or just update rewrite_rules option (soft flush). Default is true (hard).
+	 */
+	function flush_rules( $hard = true ) {
+		if ( !did_action( 'admin_init' ) ) { 
+			_doing_it_wrong( __( 'Never flush rules before admin_init, and NEVER on a front-end page load! Do it on plugin activation instead.' ) ); 
+		 	return false; 
+		}
+		if ( $hard )
+			add_filter( 'shutdown_filter_rewrite_rules_hard', '__return_true' );
+		add_action( 'shutdown', '_wp_shutdown_flush_rules' );
+	}
+	
+	/**
 	 * Remove rewrite rules and then recreate rewrite rules.
 	 *
 	 * Calls {@link WP_Rewrite::wp_rewrite_rules()} after removing the
 	 * 'rewrite_rules' option. If the function named 'save_mod_rewrite_rules'
 	 * exists, it will be called.
 	 *
-	 * @since 2.0.1
-	 * @access public
-	 * @param bool $hard Whether to update .htaccess (hard flush) or just update rewrite_rules option (soft flush). Default is true (hard).
+	 * @since 3.4
+	 * @access private
 	 */
-	function flush_rules($hard = true) {
+	function _wp_shutdown_flush_rules() {
+		if ( !did_action( 'shutdown' ) ) { 
+			_doing_it_wrong( __( 'Do not call this function directly, use flush_rules instead.' ) ); 
+		 	return false; 
+		}
 		delete_option('rewrite_rules');
 		$this->wp_rewrite_rules();
+		
+		$hard = apply_filters( 'shutdown_filter_rewrite_rules_hard', false );
+		
 		if ( $hard && function_exists('save_mod_rewrite_rules') )
 			save_mod_rewrite_rules();
 		if ( $hard && function_exists('iis7_save_url_rewrite_rules') )
