The plugin Advanced Custom Fields provides a simple, visual interface for creating metaboxes. The result is intuitive and easy for clients to edit. ACF includes several functions for pulling field values in your templates, but I recommend not using them on the frontend.
For certain field types, such as images, ACF functions generate additional database queries. Core WordPress functions achieve the same result with significantly fewer queries.
You can monitor the number of database queries on any page using the Query Monitor plugin. In testing, switching from ACF functions to
get_post_meta()reduced database queries from 146 to 22 on a single page.
Use get_post_meta Instead of get_field
There is no reason to use get_field() when you can use the WordPress core function get_post_meta().
Beyond the performance cost, ACF functions create a frontend dependency. If the plugin is deactivated or removed for any reason, visitors will see a fatal error and a blank page instead of your site.
Wrapping all ACF function calls in function_exists() prevents the fatal error, but visitors still will not see any of the metadata you entered through ACF – even though it remains in the database.
If you use core WordPress functions instead, your site continues to display all metadata normally even when ACF is inactive. The only thing you lose is the admin editing interface.
A site that shows content without an admin editing UI is far less severe than a site that does not load at all. Using ACF functions on the frontend creates a hard dependency on the plugin being active. Core WordPress functions eliminate this risk entirely.
The examples below show how to retrieve ACF data using get_post_meta() and get_option() instead of ACF functions. This approach is straightforward for standard fields but requires understanding how ACF stores data for more complex field types.
Repeater Field with get_post_meta
Suppose you allowed the client to add videos using the ACF Repeater Field, with fields for title, video URL, and thumbnail image.
Calling the repeater’s meta key returns the number of items in the repeater:
get_post_meta( get_the_ID(), 'my_videos', true );You can then loop through each item and access its sub-field values. Here is how to display the videos without using get_field():
$videos = get_post_meta( get_the_ID(), 'my_videos', true );
if ( $videos ) {
for ( $i = 0; $i < $videos; $i++ ) {
$title = esc_html( get_post_meta( get_the_ID(), 'my_videos_' . $i . '_title', true ) );
$video = esc_url( get_post_meta( get_the_ID(), 'my_videos_' . $i . '_video', true ) );
$thumbnail = (int) get_post_meta( get_the_ID(), 'my_videos_' . $i . '_thumbnail', true );
$thumbnail = $thumbnail
? wp_get_attachment_image( $thumbnail, 'medium' )
: '<img src="' . get_stylesheet_directory_uri() . '/images/default-video.png" />';
$class = ( 0 === $i % 2 ) ? 'one-half first' : 'one-half';
echo '<div class="' . $class . '"><a href="' . $video . '">' . $thumbnail . '</a>' . $title . '</div>';
}
}Notice how the ACF Image field stores the attachment ID in the database. You retrieve the actual image markup using the WordPress function wp_get_attachment_image():
wp_get_attachment_image( $image_id, 'image_size' );Options Page Data
When you add metaboxes to an ACF Options Page, the data is stored in the wp_options table, not as post meta. The key is your field name prefixed with options_.
If your options page has three fields, retrieve them like this:
$title = esc_html( get_option( 'options_title' ) );
$button_text = esc_html( get_option( 'options_button_text' ) );
$button_url = esc_url( get_option( 'options_button_url' ) );
if ( $title && $button_text && $button_url ) {
echo '<div class="call-to-action"><div class="wrap"><p>' . $title . '</p><p><a href="' . $button_url . '" class="button">' . $button_text . '</a></p></div></div>';
}Term Metadata
If you added a custom field called “Secondary Title” to categories, ACF stores this data in the wp_termmeta table (since ACF 5.5 and WordPress 4.4+). You can retrieve it using get_term_meta():
if ( ! is_category() ) {
return;
}
$category = get_queried_object();
$subtitle = esc_html( get_term_meta( $category->term_id, 'my_subtitle', true ) );
if ( $subtitle ) {
echo '<p class="subtitle">' . $subtitle . '</p>';
}In ACF versions before 5.5, term metadata was stored in the
wp_optionstable with the format[taxonomy]_[term_id]_[field_name]. Since ACF 5.5, term data is stored in thewp_termmetatable, accessible via the standard WordPress functionget_term_meta().
FAQs
Common questions about using ACF without frontend dependency:
get_post_meta() retrieves the raw value directly from the database cache, while get_field() runs additional formatting logic and may trigger extra database queries depending on the field type. For image fields and repeater fields, the difference is most significant.get_field() and ACF is deactivated, visitors will see a fatal error and a blank page. If you use get_post_meta() instead, your site continues to work normally because the data still exists in the database and WordPress core functions are always available.wp_postmeta rows. The parent repeater key stores the count of items. Each sub-field is stored with the pattern [repeater_name]_[index]_[sub_field_name]. For example, a repeater called my_videos with 3 items stores the count as my_videos = 3 and each title as my_videos_0_title, my_videos_1_title, etc.wp_options table with your field name prefixed by options_. For example, a field named title is stored as options_title. Retrieve it using the WordPress function get_option('options_title') instead of get_field('title', 'option').function_exists('get_field') prevents the fatal error if ACF is deactivated, but all custom field data will simply not appear on the frontend. Using get_post_meta() instead means the data is always displayed regardless of whether ACF is active.Summary
Using core WordPress functions like get_post_meta(), get_option(), and get_term_meta() instead of ACF’s get_field() eliminates the frontend dependency on the plugin, reduces database queries, and ensures your site continues to display content even if ACF is deactivated.
The trade-off is that you need to understand how ACF stores data in the database for each field type – but once you do, the approach is straightforward and more performant.
Here are some relevant posts:


Thanks for this awesome tips. I use ACF a lot in my designs so this helps a lot. I have one question with Repeater. What if the repeater is in the ACF options page, how would I access it using the native WordPress functions.
Do I call it say
$social_links = get_option( ‘options_social_links’ ) ;
Thanks
PC
Hi Pepin,
Yes, Thats how you call it. You will obviously need to loop through the values of the repeater field after. So if you have a field named txt in the repeater field you can display it like that: