Performance considerations when working with ACF

Advanced Custom Fields is probably my favourite WordPress plugin. For me, it unlocked the door between WordPress being a blog, and realising it’s full potential as a flexible CMS solution. It allows you to create complex pages and store data structures that just wouldn’t be possible otherwise.

One thing which I always do, though, is to look up post metadata on the front end using native WordPress functions. I don’t use get_field or have_rows, I use get_post_meta and other WordPress functions – my reasoning behind this has always been performance and the inefficiency of the ACF helper functions.

A typical use case for ACF’s repeating field is where you want to display a number of testimonials on the About page of your website. So in today’s post I wanted to set up a simple test that would show the difference in performance between a simple WordPress page, a page displaying a repeating field of testimonials using ACF’s functions, and the same page displaying testimonials using WordPress’ native functions.

I set up a new local site for testing purposes, running WordPress 4.7.3, PHP7.0.3 and the nginx web server. I installed the Genesis Sample theme and loaded the supplied dummy content. I decided that I would display testimonials on the existing Sample Page, immediately after the page content.

Without the ACF plugin installed and displaying the Sample Page, the render times and number of queries according to Query Monitor were:

StatusRender TimeMemory UsageQuery TimeDB Queries
Page Only0.15s3,745kb0.0019s27Q

To make setting up the ACF field group easier, I was able to grab the snippets of code I needed from ACF Extras, where you can find lots of other example ACF field groups and associated code snippets. In this case the repeating field had an image field, byline text field, and testimonial textarea field.

I populated the repeater field with 10 entries, and then set up a custom page template to display the repeater field using ACF’s helper functions. See page template code using ACF functions (Gist).

The page still rendered quickly, but the amount of memory used had increased as well as the number of queries run. The results were:

StatusRender TimeMemory UsageQuery TimeDB Queries
Page Only0.15s3,745kb0.0019s27Q
With ACF0.41s4,748kb0.0026s31Q

Following this test, I created a new page template which used only WordPress native functions to render the repeating field. Because I wasn’t using any ACF functions, I was also able to unload the ACF Pro plugin on the front end. See template code using WP native functions (Gist).

Following these changes, my test using Query Monitor showed:

StatusRender TimeMemory UsageQuery TimeDB Queries
Page Only0.15s3,745kb0.0019s27Q
With ACF0.41s4,748kb0.0026s31Q
No ACF0.15s3,779kb0.0019s27Q

As you can see, there is basically no discernible difference between loading our sample page without the repeating fields, and loading the page with the repeating fields displayed using WordPress’ native functions.

Because I attached the testimonials to an existing page and within the loop, all of the page meta data had already been looked up and cached when WP_Query had run, meaning our repeating field could be output without any further database queries.

The results of this test show that using ACF’s helper functions caused the page render time to increase by 173% (0.26s) and the number of queries to increase by 14% (4). Peak memory usage increased by 26% (1003kb).

Reader Interactions


  1. Craig, this is just the type of hard data that I love to see. Thanks for this! I’d love for you to add a third metric though: ACF plugin loaded, but using get_post_meta(). That would be a nice in-between. Would also be cool to see it on a page with way more (20-50?) testimonials. EIther way, nice work and thanks for sharing.

  2. Hey Craig, this is great. I ran similar tests recently and my results were about the same as yours. In fact, I found that the more complex the repeater field, the worse get_field() performed as compared to get_post_meta().

    Really, the only reason to use get_field() is the convenience factor. It can be a pain to write a whole bunch of get_post_meta() and loop through the results. That’s why I wrote a helper function as an alternative: I would be interested to hear your thoughts on that.

  3. Issue is normally going a bit crazy with flexible content and repeater fields for page layouts and content.

Leave a Reply

Your email address will not be published. Required fields are marked *