Performance & Scaling Interview Questions

Optimizing WordPress for High Traffic, Caching strategies, and Database tuning.

Performance is the #1 concern for enterprise clients. These questions test knowledge of caching layers, database optimization, and profiling.

1. Explain the different layers of caching in a WordPress stack.

Answer:

  • Browser Cache: Static assets (CSS, JS, Images) stored in the user's browser.
  • Page Cache (Varnish/Nginx/Plugin): Stores the fully rendered HTML of a page. The fastest way to serve content.
  • Object Cache (Redis/Memcached): Stores database query results (e.g., `get_option`, `get_post_meta`) in memory to avoid hitting the primary database (MySQL/Postgres).
  • Opcode Cache (OPcache): Stores compiled PHP bytecode in memory so PHP doesn't have to re-compile scripts on every request.

2. What is the N+1 Query Problem and how do you fix it in WordPress?

Answer: It happens when code executes one query to fetch a list of items, and then an additional query for each item in that list.

Example: Looping through 100 posts and getting the author name for each.

Fix:

  • Use functions that cache data automatically (WordPress core does this for many things).
  • Use `update_post_caches()` or `WP_Query` with `cache_results => true`.
  • Prefetch data. For example, if you need meta for 100 posts, fetch all meta in one query using `update_meta_cache()`.

3. How do you optimize a slow `WP_Query`?

Answer:

  • Limit fields: Use `'fields' => 'ids'` if you only need IDs.
  • No Found Rows: Use `'no_found_rows' => true` to skip counting total results (pagination) if not needed.
  • Avoid Meta Queries: Complex `meta_query` (especially with `LIKE` or multiple joins) kills performance. Use custom tables or search indexes (Elasticsearch) instead.
  • Cache Results: Ensure Object Cache is active.

4. What are Transients and when should you use them?

Answer: Transients are a standardized way to store cached data in the database (or Object Cache) with an expiration time.

Use Case: Storing the result of an expensive external API call (e.g., Instagram feed) or a complex calculation.

$data = get_transient('my_api_data');
if (false === $data) {
    $data = remote_api_call();
    set_transient('my_api_data', $data, 12 * HOUR_IN_SECONDS);
}

5. How would you debug a slow loading page?

Answer:

  1. Query Monitor: Use this plugin to see slow queries, PHP errors, and hook execution times.
  2. New Relic: For production profiling to pinpoint specific functions or external calls causing delays.
  3. WP-CLI: `wp profile` commands.
  4. Check Logs: PHP error logs and server access logs.

6. What is the difference between `wp_cache_set` and `set_transient`?

Answer:

  • `wp_cache_set` (Object Cache): Stores data in memory (RAM) for the duration of the request. If a persistent object cache (Redis/Memcached) is installed, it persists across requests. It is non-blocking and very fast.
  • `set_transient` (Database/Object Cache): Stores data in the `wp_options` table by default (with an expiration). If a persistent object cache is present, it acts like `wp_cache_set`.

Key Difference: Without an external object cache, `wp_cache_set` data is lost when the page finishes loading. Transients persist in the DB even without Redis.

7. How do you optimize the `wp_options` table?

Answer: The `wp_options` table can become bloated, slowing down every page load because "autoloaded" options are fetched on every request.

Optimization Strategies:

  • Clean up Autoloaded Data: Identify large options with `autoload='yes'` that aren't needed on every page and set them to `'no'`.
  • Remove Stale Transients: Old transients can clutter the table. Use a DB cleaner or WP-CLI `wp transient delete --expired`.
  • Index: Ensure the `autoload` column is indexed (it is by default in modern WP).

8. Explain "Lazy Loading" in the context of WordPress images.

Answer: Lazy loading defers the loading of off-screen images until the user scrolls near them. This improves the initial "Largest Contentful Paint" (LCP) score.

Implementation:

  • Native: WordPress (since 5.5) adds `loading="lazy"` attribute to `img` tags automatically.
  • Optimization: You should disable lazy loading for the "hero" image (above the fold) to ensure it loads immediately, improving LCP.
// Disable lazy loading for the first image
add_filter( 'wp_get_attachment_image_attributes', function( $attr ) {
    if ( is_hero_image() ) {
        $attr['loading'] = 'eager';
    }
    return $attr;
});