Advanced Custom Fields
ACF turns WordPress into a genuine content modelling tool. The decision that matters is not free versus Pro — it is whether your field definitions live in code or in the database.
ACF makes WordPress a content modelling tool rather than a blogging platform with extra boxes. Define fields — text, image, relationship, repeater, flexible content — attach them to a post type, and editors get a purpose-built form instead of a single body field they are asked not to break.
For any site whose content is structured, this is the difference between a maintainable build and a pile of conventions nobody documented.
What it actually adds
- A field builder: define groups of typed fields and the rules for where they appear.
- Location rules: attach fields to a post type, a page template, a taxonomy term, a user or an options page.
- Relationship fields, which is how you express that a Property has an Agent without inventing your own scheme.
- Repeaters and flexible content (Pro), for sections an editor can add and reorder.
- Template functions —
get_field(),the_field()— that read the values. - Options pages (Pro), for site-wide settings that are not attached to any post.
It pairs naturally with custom post types: the post type is the thing, ACF describes its properties.
The decision that matters: code or database
Not free versus Pro. This one.
Field groups created in the admin are database rows. They are invisible to version control, they do not travel between environments with your code, and moving a change from local to production means exporting and importing by hand — or forgetting to, and finding production missing a field.
Field groups registered in code live in a file in your repository. They deploy with everything else, they are reviewable in a diff, and every environment is guaranteed to agree.
ACF supports both, and it can export a group as PHP for you. On any site with staging — which should be any site that matters — register in code, in a site-specific plugin rather than the theme so the definitions survive a theme change. The reasoning behind that placement is the same as in custom post types explained, and the version control side is in WordPress and Git.
Field groups built in the admin are fine for a single-environment site maintained by one person. They become an operational problem the moment there are two environments or two people.
The lock-in
Milder than most plugins in its price range, and worth being precise about.
Your data survives. ACF stores values as ordinary post meta. Remove the plugin and the values are still in the database, readable with get_post_meta().
Your templates do not. Every get_field() call breaks. A theme built on ACF is a theme that requires ACF, and rewriting those calls across a template set is real work.
Complex field types are less portable. Repeaters and flexible content store their values in a structured naming scheme. It is documented and readable, but "readable" is not the same as "another plugin can use it".
The practical position: your content is safe, your build is committed. That is a good trade for what the plugin does, and it is the right trade to make knowingly.
The 2024 divergence
Worth knowing because it affects what is installed on your sites.
In 2024 the plugin's listing in the WordPress.org directory and the commercially maintained plugin diverged, and a separately maintained version now exists in the directory under a different name. Sites updating from the directory may therefore be running something other than the vendor's plugin.
Two practical actions, regardless of any view on how it happened:
- Check what each of your sites actually has installed, and where its updates come from.
- Decide deliberately which you want to track, and make sure automatic updates are not silently moving you between them.
This is a good general reminder rather than a criticism of ACF: a plugin is a supply chain, and knowing where your updates originate is part of maintaining a site.
Free versus Pro
The free version covers the common field types and the field builder. Pro adds repeaters, flexible content, the gallery field, clone fields and options pages.
Repeaters are the usual reason to buy. Once you need "an editor can add three to eight of these", the free version stops being sufficient and no amount of arranging around it helps.
Performance
ACF is efficient for what it does, and misuse is easy. The pattern to avoid is calling get_field() repeatedly inside a loop over many posts, which produces a query per field per post.
On archive pages with many items, fetch what you need deliberately rather than field by field. This is one of the more common causes of a WordPress site that is slow only on certain templates — the diagnostic order is in how to speed up a WordPress site.
Common mistakes
- Field groups in the database on a multi-environment site.
- Registering fields in the theme, so they vanish with a theme change.
- Using ACF as a page builder — flexible content can approximate one, and a design system usually serves better.
get_field()in a loop over a large archive.- No documentation of what the fields mean, leaving the next developer to infer the model from the form.
Before you build on it
Model the content on paper first: what the things are, what properties each has, and which relate to which. Then build the field groups, register them in code, and confirm a fresh clone of the repository plus a database produces the same admin screens. If it does not, something lives in the database that should not.
Frequently asked
- In code for any site with more than one environment. Field groups created in the admin are database rows, invisible to version control, and have to be exported and imported by hand between local, staging and production.
- The values survive — they are ordinary post meta. What you lose is the editing interface and the helper functions, so templates calling get_field() break. The data is recoverable; the site is not, until templates are rewritten.
- In 2024 the plugin's directory listing diverged from the commercially maintained plugin, and a separately maintained version now exists under a different name. Check which one your site actually has installed and where its updates come from.