Drupal developer

How to prevent cache_form table to get too big in Drupal 7

Posted on 31. December 2015 - 21:25 in category Drupal 7

Recently, a web hosting company I use sent me an email warning me about exceeding allowed size of the database. The limits are quite restrictive in this case. I had to deal with this issue based on a client request. I found out that the problem was in cache tables, especially the cache_fom table. It consumed about 80 % of the total space. But why?

Why Drupal needs cache_form table

This table holds CSRF (Cross-site Request Forgery) tokens for security purposes and serialized forms for security and speed purposes. It cannot be offloaded to volatile storage (Memcache, etc.). Persistent storage is mandatory. Because temporary data in this table cannot be rebuilt on the fly. That also means you should never use TRUNCATE TABLE cache_form because it leads to data loss (all open forms are invalidated). It's good to know that some forms are excluded from caching, such as login and search forms.

Did your site stop working?

When the size of the database exceeds limits, web hosters usually deny INSERT or UPDATE operations. Your site will stop working and manual action is required. Here's a quick fix. Log in to your database (phpMyAdmin, Adminer, etc.) and run this command: DELETE FROM cache_form WHERE expire < UNIX_TIMESTAMP().

How to clear cache_form regularly

Most of the time this works out of the box by regularly run cron job. Cache clearing is processed in system_cron() function. Basically it deletes expired rows in the table. However this sometimes isn't sufficient (sites with many forms or with high traffic). It might help to run the cron more frequently (once an hour). When this won't help, there is a module OptimizeDB. It should clear the cache more reliably and provide easy access to current cache_form table size in administration area.

But none of the above still didn't resolve the issues on my site.

Shorten expiration of cache_form records

Digging deeper I found out that in FORM API there is a function form_set_cache() which has hard coded expiration set to 6 hours. Value that is impossible to alter. Keeping in mind that hacking the core is like killing kittens I hoped that there must be a better way. That's why I wrote a custom cron function that alters this expiration time to 1 hour.

function hook_cron() {
// shorten cache_form expiration to 1 hour (default 6 hours).
db_query('UPDATE {cache_form} SET expire = created+3600');

Finally, I was able to stay below the web hosting's database size limits. My cache_form table is currently not bigger than 10 % of the whole database, on average.

Turn off caching for some forms

Thinking about turning off the cache for some forms? It's possible. But I do not recommended this, except if you absolutely know what you are doing. Search for $form['#token'] = FALSE; or $form_state['no_cache'] = TRUE; for more information about that.