WordPress postmeta is useful, but be careful


The add_post_meta(), delete_post_meta(), update_post_meta(), and get_post_meta() functions are really useful. It’s the perfect place to store information about a post. Many plugins take advantage of this storage for determining whether a specific post/page needs the feature they are providing or not.

Example: I recently installed on a site I manage the WordPress HTTPS plugin; it allows you to force SSL on a specific page or post of your site.

Once enabling the plugin on a page on the site I checked the “Custom Fields” section (where the postmeta fields are displayed on the post edit page) and lo and behold:

A new postmeta field had been added.

Not surprising, as I said, it’s a useful place to store information. But there is one aspect of this feature you should be aware of: it is cached on page load.

When you run the WordPress loop many wonderful things happen to make your page load as efficiently as possible. One of those things is that WordPress caches all the postmeta values when it loads the post.

This means two things:

  1. You DON’T have to worry about the amount of times you call the same value through get_post_meta(), since your server is not making a new query for each function call.
  2. You DO have to worry about how much information you are storing in the postmeta since all that information will be loaded into server memory each time the post or page is loaded. Normal storage will work fine, store things like settings, variables and content that is needed for displaying the post. But don’t think about the postmeta as a place for unlimited storage. Some things do need their own table.

What do I mean? In short, don’t store post logs or large amounts of stats and data there.

Example: I made a file uploading plugin for a client to be used internally in their company, that leverages plupload built into WordPress. I tied the backend into the company’s LDAP server so that any org member could sign into the uplaoder and not need an account created. Each file uploaded was tied to the user’s account so that they could each manage their own files. There’s a few more useful features thrown in like: file expirations, secured files, and dynamic file serving. I’ll be happy to post specs at some point. It’s pretty cool.

One feature I added was logging file access. So that when each file is accessed there is a trace of who/what/where/when. I thought: “what better place to store that information then in the postmeta?” Right? NOPE. The site ran smoothly until images uploaded were used in an email blast. The blast only went out to a few thousand people, but each time any of those images were loaded i.e. each email opened, the ENTIRE access log was loaded into the memory.

Oops.

'update_post_meta_cache' => false

Was the quick fix, and gave me time to offload the logs and refactor the code…

For more information about the power of the Loop I highly recommend watching Andrew Nacin’s talk about WP_Query, talk slides.