Designing WordPress data models that survive contact with editors.

The model that makes sense on the whiteboard rarely survives a quarter of real editorial use. Designing for that is the job.

WordPress data modeling is the most consequential decision in a custom build — and the one most agencies treat as an afterthought. Most data models that look clean on paper fall apart the first time a non-technical editor needs to do something the model didn't anticipate. Here's what changes when you design for that reality from the start.

A custom WordPress build is, before anything else, a data modeling exercise. Post types, taxonomies, fields, relationships, permissions — these are the bones the rest of the platform hangs from. Get them right and the system bends gracefully to whatever the business does next. Get them wrong and every new requirement turns into a hack on top of a hack, because the original model assumed the world looks different than it does. The thing that separates a model that works from a model that doesn’t is rarely cleverness. It’s anticipating contact with real editors.

The whiteboard model and the real one.

Most data models start clean. Three post types, two taxonomies, a handful of meta fields, a relationship between People and Articles. It’s elegant. It’s also wrong, because real editorial use surfaces patterns the whiteboard didn’t predict:

  • The thing you modeled as one post type is actually two. “Events” turns out to mean both in-person workshops and recurring webinars, and they behave differently enough that one type isn’t right for both.
  • The taxonomy you set up as flat needs to be hierarchical six months in. “Topics” was a flat list; now there are parent topics and sub-topics and the editor needs to filter by either.
  • The meta field you stored as a string needs to be queryable. “Industry” was free text; now you need to filter posts by industry and free text is the wrong type for that.
  • The relationship you modeled as one-to-many is actually many-to-many. An article has one author until the day there’s a co-authored piece.

None of these are exotic. They’re the kind of thing that happens in the first year of a CMS being used. A model that anticipates them costs slightly more to build and costs dramatically less to live with.

Patterns that compound.

A few choices that consistently age well, in roughly the order I reach for them:

  • If the thing has its own URL, it’s a post type. Don’t model individual case studies as ACF flexible-content blocks on a single page. Each case study is its own entity, with its own URL, its own meta, its own ability to be referenced from elsewhere. Use the system for what it’s good at.
  • If you’d want to filter or group by it, it’s a taxonomy. Industry, topic, tag, region, audience segment — anything where you might say “show me all posts where this property equals that value” should be a taxonomy, not a free-text meta field. Taxonomies use dedicated, indexed database tables making them incredibly fast to query; filtering by meta fields requires heavy database JOINs that will reliably kill your site’s performance at scale.
  • Relationships go in ACF Relationship fields, not custom join tables. Building your own custom join tables, or manually writing serialized relationship arrays into wp_postmeta, looks reasonable on day one and becomes unmaintainable on day 300. ACF’s Relationship field handles the common case cleanly and integrates with the editor UI for free.
  • Permissions are part of the model. If a Case Study should only be editable by the team that owns it, that’s a data-modeling decision, not a plugin-bolted-on decision. map_meta_cap exists for this reason.

What to refuse to model.

Equally important: knowing what shouldn’t be in the model at all.

  • Don’t model presentation in the data. If the editor’s choice is “hero variant A or hero variant B,” that’s content-shape, not content. The variant lives in the template logic, not the database. Otherwise every redesign requires migrating data.
  • Don’t model state machines without a reason. Posts have a status (draft/publish). Some clients want more — review, approval, scheduled-with-conditions. Every status you add is a workflow you have to maintain. Earn each one.
  • Don’t model the org chart. If your client has a Marketing department and an Engineering department, that’s a permissions question, not a data-model question. Adding a “department” field to every post type bakes today’s org chart into tomorrow’s data.

The discipline of revisiting the model.

The model you ship in version 1 is going to be wrong in some specific ways by version 1.5. The healthiest WordPress platforms are the ones whose owners audit the data model annually and refactor when patterns drift. The cost of a model refactor in year two is real but bounded. The cost of pretending the original model still fits when it doesn’t is unbounded — every subsequent feature works around it, every workaround is its own future problem.

This is the work that platform architecture exists to do. It looks like configuration. It’s actually design.

Let's talk about what you're building

No proposals. No pitch decks. Just a conversation about your project and whether I'm the right fit to build it.

Start a Conversation