Performance concerns related to usage of attachment_url_to_postid, image locking feature

Hi there!

I’m not a user of the plugin nor am I looking for support but I wanted to share some notes from some recent triaging that I recently posted on Performance issues, attachment_url_to_postid | WordPress.org

Essentially, the plugin appears to have a feature that can have a severe impact on a site’s performance.

I believe this may be the image locking feature I’ve seen referenced but I haven’t reviewed your plugin’s options in detail yet, just its behavior.

It might be good to review other more performant and optimized options for achieving the feature’s goal.

Extended details

I’ve recently triaged a case where a site was experiencing some performance issues. The site was making excessive database queries, leading to very slow requests and throttling.

After examining things closer, we found that every image on each page and post were leading to a query for the image and various subsizes, like the following.

SELECT post_id, meta_value FROM wp_postmeta WHERE meta_key = '_wp_attached_file' AND meta_value = '2022/03/example-image.jpg'

SELECT post_id, meta_value FROM wp_postmeta WHERE meta_key = '_wp_attached_file' AND meta_value = '2022/03/example-image-300x163.jpg'

SELECT post_id, meta_value FROM wp_postmeta WHERE meta_key = '_wp_attached_file' AND meta_value = '2022/03/example-image-200x108.jpg'

SELECT post_id, meta_value FROM wp_postmeta WHERE meta_key = '_wp_attached_file' AND meta_value = '2022/03/example-image-400x217.jpg'`

Examining the stack trace for these requests led to this:

Patreon_Compatibility->jetpack_photon_skip_image, attachment_url_to_postid

I see the plugin has a compatibility fixer to try to identify gated images and disable the Jetpack Photon Image CDN for them.

https://plugins.trac.wordpress.org/browser/patreon-connect/trunk/classes/patreon_compatibility.php?rev=2344387#L705

Note that this may lead to severe performance issues on sites with a lot of images and traffic. This can slow down a site, lead to throttling from a host, and cause a site to hit PHP connection limits. More affordable hosting options may encounter significant database load.

Other plugins have struggled with similar issues. Some users work around this by adding a custom index.

It may be worth reviewing further and finding a more optimized solution.

We were experiencing the same issues and reported it to wordpress.com support (this is where we host). They investigated for us and responded with the following.

Hi there!

My colleagues let me know of the 429 errors you were encountering on the site at [mydomain]. Thank you for your patience while we continued to review this.

Findings

We took a closer look and identified that our servers are operating normally; however, your site’s plugins and code are causing some performance issues.

While we will not be able to make server or developer adjustments to alleviate the issues your site is causing, I will provide information about our findings and potential next steps.

429 & 599 Errors

The 429s you’re encountering are not typical rate-limiting issues. While they appear as 429s to you and visitors, we log these internally as 599. I’ll refer to these as 599s throughout the rest of my message.

Rather than being normal 429s, your site is making many requests that are not optimized or performance. The requests are might be occurring too quickly, too often, and may be taking too long to complete due to code issues.

This leads to your site being limited temporarily until the pending requests are completed, timeout, or are generally reduced.

Causes

The 599s seem to have been caused by two primary situations

  • Users simply interacting with the site
  • Admins/editors making edits.

It is the requests being made during these situations that lead to the rate-limiting. As mentioned, there are a number of performance issues that appear to be contributing to this and I will cover those next.

Queries

Some posts and pages on the site make an excessive number of queries.

Specifically, at times there may be hundreds of queries like the following running at the time time. This make for slow and unoptimized requests that can cause your site to utilize too many PHP connections.

SELECT post_id, meta_value FROM wp_postmeta WHERE meta_key = '_wp_attached_file' AND meta_value = '2019/05/Witchmothers-Potent-Brew-Food.jpg'

We then see the same query for each subsize of the image. This results in hundreds of requests on a large majority of your pages.

Here is a stack track for what is generating the query.

require('wp-blog-header.php'), require_once('wp-includes/template-loader.php'), include('/themes/Avada/100-width.php'), the_content, apply_filters('the_content'), WP_Hook->apply_filters, do_shortcode, preg_replace_callback, do_shortcode_tag, FusionSC_Container->render, do_shortcode, preg_replace_callback, do_shortcode_tag, Fusion_Row_Element->render, do_shortcode, preg_replace_callback, do_shortcode_tag, Fusion_Column_Element->render, do_shortcode, preg_replace_callback, do_shortcode_tag, FusionSC_Imageframe->render, fusion_add_responsive_image_markup, wp_filter_content_tags, wp_img_tag_add_srcset_and_sizes_attr, wp_image_add_srcset_and_sizes, wp_calculate_image_srcset, apply_filters('wp_calculate_image_srcset'), WP_Hook->apply_filters, Jetpack_Photon->filter_srcset_array, apply_filters('jetpack_photon_skip_image'), WP_Hook->apply_filters, Patreon_Compatibility->jetpack_photon_skip_image, attachment_url_to_postid

While examining this closer, we found that this seems to be a conflict between the `Patreon WordPress plugin and our Image CDN. The content loads in, Avada (Fusion) Builder renders the image, and our Image CDN generates the necessary source set and subsizes.

Then, the Patreon Wordpress plugin performs some sort of compatibility check and “fix”, Patreon_Compatibility->jetpack_photon_skip_image, attachment_url_to_postid .

This is what then causes the excessive requests. We recommend not using these two tools together for now and it may be necessary to contact the developer of the Patreon WordPress plugin if you find you would like to use our Image CDN again.

Next Steps

To help alleviate this, we’ve deactivated our Jetpack Image CDN module. This prevents the excessive number of requests Patreon WordPress would normally make without much, if any, negative impact on your content and performance.

If you would ever like to enable the Image CDN again, it can be toggled on by visiting My Site > Settings > Performance. There toggle on the button next to Speed up image load times . I do not recommend enabling this with the `Patreon WordPress plugin active. Not until they make changes to prevent this issue.

Your site hasn’t experienced 599s for the last few days and we have made some accommodations to assist with reducing load of server requests. With these changes, specifically the deactivation of the Image CDN, I would not expect this specific issue to occur again.

This feature should only kick in if someone enables ‘Image locking’ feature. In cases in which the user enables the feature, then disables it but the .htaccess file is not updated, it can still recur.

In respect to the performance impact of the feature: Indeed, image locking requires noticeable performance even without looking for different sizes of the same image in attachments db. That’s why we have a notice next to the setting that enables it.

As for the particular code that checks for different size attachments for the same image: This was implemented after non-qualifying users (non patrons) were found to be accessing different sizes of a locked image, therefore circumventing the gating. Its a necessary feature, albeit requiring performance. I will look into optimizing that routine, but the wiggle room may be limited.

Do you have the image locking feature on? That needs to be confirmed. If the image locking feature is not on, and yet you are experiencing this, then this is a bug that must be addressed.

If you are using the image feature however, CDN is not something that you should be using because CDN will cause the image locking to be circumvented with CDN frequently caching the non-locked image and showing it to the users. So image locking feature is not something that should work with Jetpack in any case.

No, the image locking feature is off. We have never used it.

Can you or your web host check your .htaccess file to confirm if the below lines are in it?

# BEGIN Patreon WordPress Image Protection
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_FILENAME} (.png|.jpg|.gif|.jpeg|.bmp)
RewriteCond %{HTTP_REFERER} !^wp-admin [NC]
RewriteRule ^" . $upload_dir . "/(.*)$ index.php?patreon_action=serve_patron_only_image&patron_only_image=$1 [QSA,L]
# END Patreon WordPress

As far as I am aware we do not have a .htaccess file as we use NGINX and not Apache. @verygoode Please correct me if I’m wrong.

In that case, the equivalent rules in Nginx config for that virtual host must be checked.

I’m hosting on wordpress.com, I unfortunately cannot tell you the specific nginx configuration used. But I highly doubt those impact the statements that are causing the performance issues here. The plugin should not be touching my CDN content in any case with the image locking setting off.