expect Scaling is a problem you WANT to face and it is going to happen sooner or later. • How to prepare General stuff you can do to make your WordPress installations lighter and less prone to heavy traffic. • How to react So, you are prepared now! So, your website's traffic increases. What do you do then?
• High traffic (traffic is traffic, obviously) • Poor server/hosting performance • Database clogging (do you actually know what queries your WordPress runs in the background when you do a query_posts?) • Spikes. Those dreaded spikes! Server killer
• Number of admins • Number of concurrent users • Frequency of content updates (is it a personal blog or a mighty portal?) • Customization complexity (what you do with all these filters and hooks!) • Services that cannot be cached • Comments • Competitions • Forms, ajax calls, etc
• Days to watch out for • Monday • Tuesday • Wednesday • Thursday • Hours to watch out for • Morning ~ 11:00 – 13:00 • Afternoon ~ 15:00 – 19:00 • Night ~ 22:00 – 24:00 • (That's nice! So, I have to be on the watch out 24/7?)
WordPress is a simple CMS • Database architecture is very simple • For posts: wp_posts wp_postmeta • For taxonomies: wp_terms wp_term_relationships wp_term_taxonomy * but you do have a table for links • It is over-generalized • A fit-for-all solution • Therefore: not optimized!
old post revisions from the database • Set revisions not too often • Set number of revisions retained low • Use as little as possible custom thumbnail sizes • Cleanup old sticky posts • Avoid customization of frequent hooks and filters like "pre_get_posts" • Avoid long post/taxonomy "not-ins"
just showing off) AND ( wp_posts.ID NOT IN ( SELECT object_id FROM wp_term_relationships WHERE term_taxonomy_id IN (1) ) ) AND wp_posts.post_type IN ('videos', 'galleries', 'competitions', 'post', 'nav_menu_item') AND (wp_posts.post_status = 'publish' OR wp_posts.post_status = 'future' OR wp_posts.post_status = 'draft' OR wp_posts.post_status = 'pending' OR wp_posts.post_status = 'trash' OR wp_posts.post_status = 'auto-draft' OR wp_posts.post_status = 'inherit' OR wp_posts.post_status = 'private') AND ( (wp_postmeta.meta_key = 'day_new' AND CAST(wp_postmeta.meta_value AS CHAR) = 'true') ) GROUP BY wp_posts.ID ORDER BY wp_posts.post_date DESC LIMIT 0, 1 Yeah, right!
on • Probably the single most important technique • Useful no matter how big your site is • All websites need to use caching • There are two areas where you can cache • The server • The browser (try to remain calm)
whole requests Use plugins like W3 Total Cace or Hyper Cache • Object and query cache Same plugins, but use it yourself, too (remember WordPress transients) • HTML fragment cache For instance cache the sidebar contents • Opcode cache Use APC in Apache for PHP Opcode caching (mostly useful in big monolithic websites)
eliminate redundant requests • Add expires headers • Favicons -almost- never change • Font files -almost- never change • Styles and scripts rarely change • Images also rarely change (new ones appear, but old ones rarely change) • HTML might change often (it depends) • Be prepared to un-cache (invalidate) content In order to minimize requests
Some tips • "Always be prepared" • Step by step • Child ~1.000 page views • Teenager ~10.000 page views • Adult ~150.000 page views • Maturity ~1.000.000 page views • Immortality ~scales out (millions of page views) A shared hostinng is fine Must cache (W3C Total Cache, Hyper-Cache etc) A dedicated server is appropriate An extra cache server (Varnish) will do the job CDN: it costs but it gets the job done (tweaking is still necassary)
• You can always use a CDN even from early on • Akamai • CloudFront • CloudFlare • AWS • Or a dedicated/managed WordPress hosting service • http://wpengine.com/ • http://zippykid.com/ • https://page.ly/ • http://websynthesis.com/ (just throwing some names, not recommending anything)