23
asynchronous personalization [and CDNs and A/B testing and stuff] Jon Pliske Performance Engineering, Groupon @jonpliske [email protected]

Asynchronous Personalization at Groupon - JSConf 2011

Embed Size (px)

DESCRIPTION

Slides from my talk at JSConf 2011. Covers the usage of asynchronous personalization, CDNs, and A/B testing with Finch.js at Groupon.

Citation preview

Page 1: Asynchronous Personalization at Groupon - JSConf 2011

asynchronous personalization[and CDNs and A/B testing and stuff]

Jon PliskePerformance Engineering, Groupon

@[email protected]

Page 2: Asynchronous Personalization at Groupon - JSConf 2011

Jon PliskePerformance Engineering, Groupon

@[email protected]

You might know me from this leaked photo on TechCrunch

Page 3: Asynchronous Personalization at Groupon - JSConf 2011

overview

backgroundCDN cachingasync personalizationa/b/multivariate testing /w finch.js

Page 4: Asynchronous Personalization at Groupon - JSConf 2011

performance anxiety

big rails appbig teambig traffic

performance issuesdevelopment process hurdlesdrinking problems

===

Reaching limit of Rails' cachingLow-level optimizations too "incremental"Rewriting SQL is boringImprove platform architecture

Page 5: Asynchronous Personalization at Groupon - JSConf 2011

super bowl party

prelude:jan 1. "btw we have pre/post super bowl commercials"jan 15. "scored an in-game spot, we good?"feb 15. offend the world

"spike mode":CDN cache it all!disable loginoffload geocoding/subscriptions/orders to EC2limited functionality === unhappy users

Page 6: Asynchronous Personalization at Groupon - JSConf 2011

pics or it didn't happen

Page 7: Asynchronous Personalization at Groupon - JSConf 2011

pics or it didn't happen

Page 8: Asynchronous Personalization at Groupon - JSConf 2011

CDNs are neatproslow latency"edge side nodes"high capacitystatic content

consdynamic contentpersonalizationcomplexityoverkill?

specifically:personalized content (login menu, deals)analytics trackinga/b testingRails developers

Page 9: Asynchronous Personalization at Groupon - JSConf 2011

async personalizationtarget: deal/division pages (> 50% of traffic)

approach:1. cache "anonymous" page in CDN2. hide stuff3. make AJAX request for personalized data/content4. show stuff

See Chris Williams' "Rails’ Best Caching Method is JavaScript"from GoRuCo 2010

Page 10: Asynchronous Personalization at Groupon - JSConf 2011

obligatory omnigraffle diagram

Page 11: Asynchronous Personalization at Groupon - JSConf 2011
Page 12: Asynchronous Personalization at Groupon - JSConf 2011
Page 13: Asynchronous Personalization at Groupon - JSConf 2011

"Anonymous" userbefore:initial page response time: 0.8 sec rendering time (e.g. loading css/js/images): 1 sec total: 1.8 sec

after:initial page response time: 0.1 secrendering time: 1 sectotal: 1.1 sec

only a little bit faster...(1.1 vs 1.8 sec)basically no server load => huge capacity increase!

Page 14: Asynchronous Personalization at Groupon - JSConf 2011

Logged-in User / Subscriberbefore:initial page response time: 3 secrendering time (e.g. loading js/css/images): 1 sec total time: 4 sec

after:initial page response time: 0.1 secrendering time (include AJAX call:1 sec): 1 sectotal time: 1.1 sec

Capacity constant: AJAX call still needs to hit Rails300% faster!

Page 15: Asynchronous Personalization at Groupon - JSConf 2011

[wait for applause]

Page 16: Asynchronous Personalization at Groupon - JSConf 2011

development implications

less Rails, more JS1 user !== 1 (Rails) request

goodbye:current_usersessioncookies

testing

Page 17: Asynchronous Personalization at Groupon - JSConf 2011

onCurrentUserReady(callback)callback when personalize API returns (or callback immediately for anonymous user)

before:- if logged_in? do stuff for logged-in user- else do stuff for anonymous user

after:Groupon.onCurrentUserReady(function(){ if (Groupon.currentUser.isAuthenticated) { do stuff for logged-in user } else { do stuff for anonymous user }});

Page 18: Asynchronous Personalization at Groupon - JSConf 2011

analyticsProblem: Request loggingSolution: Tracking pixel (hit Nginx only, not Rails)

Problem: Content changesSolution: Dynamic tracking pixel

Problem: Tracking params (e.g. utm params, affiliate id, etc...)Solution: Store in cookie; append params to API request

Page 19: Asynchronous Personalization at Groupon - JSConf 2011

a/b testing with FinchProblem: Finch uses view/controller logic to choose and track experiments and variants

- experiment 'Two vs. Three Step Subscription' do |e|

- e.variant 'Original' do %h1 Fill out this form to subscribe now

- e.variant 'Two Step' do %h4 Follow these two steps to subscribe

- e.variant 'Three Step' do %p Subscribe now - it only takes a few seconds

Page 20: Asynchronous Personalization at Groupon - JSConf 2011

Finch.jsFinch.Experiments.DelayedJSExperiment = { defer: function() { var experiment = this; FinchDemo.onCurrentUserReady(function() { experiment.deferedRun(this); }); }, before: function() { $('#delayed').hide(); }, after: function() { $('#delayed').show(); }, variants: { original: function() { $('#delayed .original').show(); }, alternate: function() { $('#delayed .alternate').show();}, } }; $(function() { Finch.run(window); });

Page 21: Asynchronous Personalization at Groupon - JSConf 2011

Finch.jsbased on Google's "Overlapping Experiment Infrastructure"written in coffee-scriptopen source soon-ishly~ 15k of JSdoesn't handle tracking/analytics/analysis side of testing (yet?)

Page 22: Asynchronous Personalization at Groupon - JSConf 2011

the futurepure-JSON API requestsclient-side rendering (/w mustache.js)HTML5 storagedecouple from Rails

development practices:front/back-end integrationbetter testingbetter monitoring

Page 23: Asynchronous Personalization at Groupon - JSConf 2011

@[email protected]/techjobs

Thank you!