[@indeedeng] managing experiments and behavior dynamically with proctor

180
Proctor Managing A/B Tests and More

Upload: indeedeng

Post on 25-Dec-2014

2.972 views

Category:

Technology


1 download

DESCRIPTION

Video available at: http://youtu.be/Q1T5J0KXUwY At this very moment, Indeed is running more than one hundred A/B experiments. In previous @IndeedEng talks, we have discussed how we use A/B testing to develop better products. In this tech talk, software engineer Matt Schemmel and product manager Tom Bergman describe Proctor, the system we developed to define and manage all of these experiments. They explain how we use Proctor to target users using data-driven rules, adjust experiments on-the-fly, and ensure clean results for multi-variate tests. Over time, Proctor has evolved from a system designed for managing experiments to one that manages overall system behavior through dynamic "feature toggle" functionality. Matt and Tom also share lessons we have learned from years of experimenting at web scale. Matt Schemmel is a Senior Software Engineer working primarily on our Resume products. Tom Bergman is a Product Manager currently working on our Aggregation systems. He previously helped evolve many of Indeed's data analysis tools, and also helped us launch and grow our sites in Japan, Korea, and China.

TRANSCRIPT

Page 1: [@IndeedEng] Managing Experiments and Behavior Dynamically with Proctor

ProctorManaging A/B Tests and More

Page 2: [@IndeedEng] Managing Experiments and Behavior Dynamically with Proctor
Page 3: [@IndeedEng] Managing Experiments and Behavior Dynamically with Proctor

Tom BergmanProduct ManagerAggregation

Matt SchemmelSoftware Engineer

Resume

Page 4: [@IndeedEng] Managing Experiments and Behavior Dynamically with Proctor

We help people get jobs.

Page 5: [@IndeedEng] Managing Experiments and Behavior Dynamically with Proctor

What's best for thejob seeker?

Page 6: [@IndeedEng] Managing Experiments and Behavior Dynamically with Proctor

Test & Measure EVERYTHING

Page 7: [@IndeedEng] Managing Experiments and Behavior Dynamically with Proctor

A/B Testing: Definition

A/B testing is an experimental methodology comparing at least two variants, a control group A and test group B, in a controlled experiment

Page 8: [@IndeedEng] Managing Experiments and Behavior Dynamically with Proctor

A/B Testing Key Points

1. Unbiased2. Independent3. Representative

Test and Control Groups should be:

Page 9: [@IndeedEng] Managing Experiments and Behavior Dynamically with Proctor
Page 10: [@IndeedEng] Managing Experiments and Behavior Dynamically with Proctor
Page 11: [@IndeedEng] Managing Experiments and Behavior Dynamically with Proctor
Page 12: [@IndeedEng] Managing Experiments and Behavior Dynamically with Proctor

103 tests315 variations

2^147 combinations

Page 13: [@IndeedEng] Managing Experiments and Behavior Dynamically with Proctor
Page 14: [@IndeedEng] Managing Experiments and Behavior Dynamically with Proctor
Page 15: [@IndeedEng] Managing Experiments and Behavior Dynamically with Proctor
Page 16: [@IndeedEng] Managing Experiments and Behavior Dynamically with Proctor

Control

Page 17: [@IndeedEng] Managing Experiments and Behavior Dynamically with Proctor

10% test

10% test

10% test

10% test

10% test

10% test

Control

Page 18: [@IndeedEng] Managing Experiments and Behavior Dynamically with Proctor

+2.9%

+2.3%

+2.0%

+5.2%

+12.8%

+9.6%

Control

Page 19: [@IndeedEng] Managing Experiments and Behavior Dynamically with Proctor

+2.9%

+2.3%

+2.0%

+5.2%

+12.8%

+9.6%

+614M emails

Control

Page 20: [@IndeedEng] Managing Experiments and Behavior Dynamically with Proctor

Why A/B Testing?

Page 21: [@IndeedEng] Managing Experiments and Behavior Dynamically with Proctor

Before and After

Before and After is bad science.

Page 22: [@IndeedEng] Managing Experiments and Behavior Dynamically with Proctor

Weekly TrafficV

isito

rs

ThurWedMon Tues Fri

Page 23: [@IndeedEng] Managing Experiments and Behavior Dynamically with Proctor

Yearly TrafficV

isito

rs

Page 24: [@IndeedEng] Managing Experiments and Behavior Dynamically with Proctor

Mid Year Test

A < B

AB

Vis

itors

Page 25: [@IndeedEng] Managing Experiments and Behavior Dynamically with Proctor

End of Year Test

AB

A > B

Page 26: [@IndeedEng] Managing Experiments and Behavior Dynamically with Proctor

Obligatory XKCD Comic

Page 27: [@IndeedEng] Managing Experiments and Behavior Dynamically with Proctor

History of A/B Testing @Indeed

Page 28: [@IndeedEng] Managing Experiments and Behavior Dynamically with Proctor

Next we tried ...

● Multiple Code Versions

● Separate Configuration

● "Sampling by Load Balancer"

Page 29: [@IndeedEng] Managing Experiments and Behavior Dynamically with Proctor

Load Balancer: Multiple Versions

CONTROL TEST

Load Balancer

(Old Version Code) (New Version Code)

Page 30: [@IndeedEng] Managing Experiments and Behavior Dynamically with Proctor

Load Balancer: Multiple Versions

1. Tedious2. Expensive3. Inflexible

It worked, but ...

Page 31: [@IndeedEng] Managing Experiments and Behavior Dynamically with Proctor

Finally ...

1. Arbitrarily Group Users2. Select Test Groups3. Implement Variations

Built Libraries, hand-write code per test to:

Page 32: [@IndeedEng] Managing Experiments and Behavior Dynamically with Proctor

Custom Coded Tests

1. Sophisticated Tests2. Scientifically Valid Methods3. Low Operational Overhead

Allowed us:

Page 33: [@IndeedEng] Managing Experiments and Behavior Dynamically with Proctor

Custom Coded Tests: Stats

Page 34: [@IndeedEng] Managing Experiments and Behavior Dynamically with Proctor
Page 35: [@IndeedEng] Managing Experiments and Behavior Dynamically with Proctor

Goals:

1. Increase Engineering Velocity2. Standardize Representation3. Work Seamlessly Across Products

Page 36: [@IndeedEng] Managing Experiments and Behavior Dynamically with Proctor

ProctorIndeed’s Java Framework for

Managing A/B Tests and More

Page 37: [@IndeedEng] Managing Experiments and Behavior Dynamically with Proctor

ProctorIndeed's Open Source Java Framework for

Managing A/B Tests and More

github.com/indeedeng/proctor

Page 38: [@IndeedEng] Managing Experiments and Behavior Dynamically with Proctor

Using Proctor

1. Background and Design

2. Running A/B Tests with Proctor

3. Beyond the Basics

Page 39: [@IndeedEng] Managing Experiments and Behavior Dynamically with Proctor

Background and Design

Page 40: [@IndeedEng] Managing Experiments and Behavior Dynamically with Proctor

Running a Test

1. Define the Experiment2. Select Groups3. Implement the Behavior4. Log the Results

Page 41: [@IndeedEng] Managing Experiments and Behavior Dynamically with Proctor

Running a Test

1. Define the Experiment2. Select Groups3. Implement the Behavior4. Log the Results

Page 42: [@IndeedEng] Managing Experiments and Behavior Dynamically with Proctor

Existing Behavior

Page 43: [@IndeedEng] Managing Experiments and Behavior Dynamically with Proctor

Save Alert

Test Behavior

Page 44: [@IndeedEng] Managing Experiments and Behavior Dynamically with Proctor

Define the Experiment

1. Buckets

2. Sample Sizes

Key characteristics:

Page 45: [@IndeedEng] Managing Experiments and Behavior Dynamically with Proctor

Control: Gray Test: Blue

50% 50%

Page 46: [@IndeedEng] Managing Experiments and Behavior Dynamically with Proctor

Define the Experiment

(global)

Division of Responsibilities

Test Definition

Apply the Experiment

(each product)

Proctor Library

Test Specification

Page 47: [@IndeedEng] Managing Experiments and Behavior Dynamically with Proctor

Buckets Enumerate the Test Variations

● ID, for code

● Long Description, for people

● Short Name, for people

Page 48: [@IndeedEng] Managing Experiments and Behavior Dynamically with Proctor

0"Control Group"Gray

1"Test Group"

Blue

Page 49: [@IndeedEng] Managing Experiments and Behavior Dynamically with Proctor

Sizing the Buckets

1. Buckets

2. Sample Sizes

Page 50: [@IndeedEng] Managing Experiments and Behavior Dynamically with Proctor

Selecting a Test Bucket

Good user experience does, too:

● Fast● Consistent

Good science requires good sampling:

● Independent● Unbiased

Page 51: [@IndeedEng] Managing Experiments and Behavior Dynamically with Proctor

Assign each subsequent visitor to the next bucket.

Round robin assignment

FastUnbiasedConsistent

Independent✓ ✓~✘

● Requires global state for "next bucket"

● Requires state for assigned buckets

Page 52: [@IndeedEng] Managing Experiments and Behavior Dynamically with Proctor

At small scale, you might need round-robin to ensure equal sample sizes.

At large scale, randomized assignment is uniform enough.

Randomized Assignment

FastUnbiasedConsistent

Independent✓ ✓??

Page 53: [@IndeedEng] Managing Experiments and Behavior Dynamically with Proctor

Select a bucket at random at the point of execution.

Roll the dice as needed

FastUnbiasedConsistent

Independent✓ ✓✘✓

Page 54: [@IndeedEng] Managing Experiments and Behavior Dynamically with Proctor

Roll Once and Cache in a Cookie

● Single-domain, Single-device

● N cookies: Hard to evolve

● One cookie: Fragile to edit

● Size scales with # experiments

FastUnbiasedConsistent

Independent✓ ✓~~

Page 55: [@IndeedEng] Managing Experiments and Behavior Dynamically with Proctor

Roll Once and Cache in Session

● Consistent only to length of session

● Tied to one server / data-center

● Many apps don’t use sessions

FastUnbiasedConsistent

Independent✓ ✓✘~

Page 56: [@IndeedEng] Managing Experiments and Behavior Dynamically with Proctor

Roll Dice and Cache in DB

FastUnbiasedConsistent

Independent✓ ✓~✘

● DB hit on every request

● More infrastructure

Page 57: [@IndeedEng] Managing Experiments and Behavior Dynamically with Proctor

We can do better

Flaws stem from the need to record selected buckets.

What if we didn't?

Page 58: [@IndeedEng] Managing Experiments and Behavior Dynamically with Proctor

1. Assign each user a unique ID

2. Map that ID to a bucket

3. Store the ID, not the assignments

Don’t Record. Recalculate.

FastUnbiasedConsistent

Independent ??

??

Page 59: [@IndeedEng] Managing Experiments and Behavior Dynamically with Proctor

Simple Mapping: Mod N

id mod N=> bucket

Doesn’t work:● Should provide uniform distribution;

mod N assumes it.

● Limited bucket distributions

Page 60: [@IndeedEng] Managing Experiments and Behavior Dynamically with Proctor

Range Mapping

id / MAX_ID => bucket

testcontrol0 10.5

Page 61: [@IndeedEng] Managing Experiments and Behavior Dynamically with Proctor

Buckets can be any size

1(inactive)

testcontrol0 10.5

testcontrol0 10.5

Page 62: [@IndeedEng] Managing Experiments and Behavior Dynamically with Proctor

testcontrol0 10.5

Sequential IDs No Longer UniformMAX_ID

2

Unbiased✘

Page 63: [@IndeedEng] Managing Experiments and Behavior Dynamically with Proctor

Hashed Range Mapping

hash ( id ) => bucket

Kept:

● Arbitrary bucket allocations ok

testcontrolMIN_INT MAX_INT0

Page 64: [@IndeedEng] Managing Experiments and Behavior Dynamically with Proctor

Unbiased Distribution for Any ID

50 / 50:

33 / 33 / 33:

Unbiased✓

Page 65: [@IndeedEng] Managing Experiments and Behavior Dynamically with Proctor

But is it independent?

Sign Up Activatevs

Sign Up Sign Upvs

Page 66: [@IndeedEng] Managing Experiments and Behavior Dynamically with Proctor

Should look like this

25% 25%

25% 25%

Sign Up

Sign Up Activate

Activate

Page 67: [@IndeedEng] Managing Experiments and Behavior Dynamically with Proctor

But our inputs are consistent

hash ( id ) => bucket

testcontrolMIN_INT MAX_INT0

Page 68: [@IndeedEng] Managing Experiments and Behavior Dynamically with Proctor

So our buckets are identical

S A S S A S A A A S A S A

Col

or

S S S S S SA A A A A A AText

Page 69: [@IndeedEng] Managing Experiments and Behavior Dynamically with Proctor

And we look like this

50% 0%

0% 50%

Sign Up

Sign Up Activate

Activate

Independent✘

Page 70: [@IndeedEng] Managing Experiments and Behavior Dynamically with Proctor

Add Salt to Test

hash ( id + test.salt ) => bucket

Kept:

● Arbitrary bucket allocations

● Uniform distribution

Page 71: [@IndeedEng] Managing Experiments and Behavior Dynamically with Proctor

Uncorrelated Distribution

A S A S A S S A A A S S A

Col

or

A S A S A S S A A A S S A

Text

Independent✓

Page 72: [@IndeedEng] Managing Experiments and Behavior Dynamically with Proctor

But is it fast?

0.90

0.85

0.80

0.75

0.70

0.65

0.60

Resume Editor Resume Search

Page 73: [@IndeedEng] Managing Experiments and Behavior Dynamically with Proctor

But is it consistent?

Consistency bounded only by ID

Page 74: [@IndeedEng] Managing Experiments and Behavior Dynamically with Proctor

We Usually Use Tracking Cookies

● Easy

● Ubiquitous on the web

● Require no server-side storage

● Best we can do with no user action

Consistent~

Page 75: [@IndeedEng] Managing Experiments and Behavior Dynamically with Proctor

FastUnbiasedConsistent

Independent✓ ✓~✓

Best we’ve seen so far…

Page 76: [@IndeedEng] Managing Experiments and Behavior Dynamically with Proctor

Definitions Map Buckets to ID Range

Bucket Range

gray 0.50

blue 0.50

Each bucket maps to a % of the hashed range

Page 77: [@IndeedEng] Managing Experiments and Behavior Dynamically with Proctor

Sometimes, Though, Cookies Won't Do

● Cross-Domain● Some People Block Cookies

● Cross-Device● Cookies are Web-Only

Page 78: [@IndeedEng] Managing Experiments and Behavior Dynamically with Proctor

Many Ways to ID a User

Account #12345

Tracking cookie:UID#1

Email [email protected]

Access Token:4/rymOMYE…

Session ID557206C363F…

Page 79: [@IndeedEng] Managing Experiments and Behavior Dynamically with Proctor

Proctor Uses Any Set of IDs

ID Type... Tracked By...

USER Tracking Cookie

ACCOUNT Account ID

EMAIL Email Address

… …

We use…

Page 80: [@IndeedEng] Managing Experiments and Behavior Dynamically with Proctor

Account ID

● Authenticated

● Consistent across domains

● Consistent across devices

● Consistent across visits

Page 81: [@IndeedEng] Managing Experiments and Behavior Dynamically with Proctor

Email Address

● Sometimes available without account

● Identified, though not authenticated

Page 82: [@IndeedEng] Managing Experiments and Behavior Dynamically with Proctor

Each Test Applies to One ID Type

● Test groups split by that identifier

● Visitors without that identifier are ignored

Page 83: [@IndeedEng] Managing Experiments and Behavior Dynamically with Proctor

Running A/B Tests

Page 84: [@IndeedEng] Managing Experiments and Behavior Dynamically with Proctor

Test Definitions Encoded in JSON

● Compact

● Simple and Flexible

● Editable by Humans

● Editable by Machines

Page 85: [@IndeedEng] Managing Experiments and Behavior Dynamically with Proctor

Basic Data in the Test Definition

"description": "Button colors","salt": "buttonBgColorTst","type": "USER"

Page 86: [@IndeedEng] Managing Experiments and Behavior Dynamically with Proctor

Buckets in the Test Definition

"buckets": [{"id": 0, "name": "gray","description": "Control group"

}, {"id": 1, "name": "blue","description": "Test group"

}]

Page 87: [@IndeedEng] Managing Experiments and Behavior Dynamically with Proctor

Mapping Buckets to Ranges

"ranges": [{"bucketValue": 0,"length": 0.5

}, {"bucketValue": 1,"length": 0.5

}]

Page 88: [@IndeedEng] Managing Experiments and Behavior Dynamically with Proctor

Complete Test Definition{

"description": "Button colors",

"type": "USER",

"salt": "buttonBgColorTst",

"buckets": […],

"allocations": [{

"ranges": […]

}],

}

Page 89: [@IndeedEng] Managing Experiments and Behavior Dynamically with Proctor

Define the Experiment

proctor data

Division of Responsibilities

Test Definition

Apply the Experiment

(each product)

Proctor Library

Test Specification

Page 90: [@IndeedEng] Managing Experiments and Behavior Dynamically with Proctor

Proctor includes several modules

Proctor

Common

Ant Builder

Codegen

Maven Builder

Page 91: [@IndeedEng] Managing Experiments and Behavior Dynamically with Proctor

Product Test Specification lists active tests

References into the global pool:

"tests": [{"buttonBgcolorTest": {"buckets": {"gray": 0, "blue": 1

}}

}]

Page 92: [@IndeedEng] Managing Experiments and Behavior Dynamically with Proctor

Apply the Experiment

On every request…

1. Select Groups2. Render the Response

3. Log the Action

Page 93: [@IndeedEng] Managing Experiments and Behavior Dynamically with Proctor

On every request…

1. Collect identifiers

2. Select buckets for opted-in tests

Determining Buckets in Code

Page 94: [@IndeedEng] Managing Experiments and Behavior Dynamically with Proctor

Collect identifiers for all ID Types

// Product codeString cookie = getTrackingCookie(request);String accountId = getAccountIdOrNull(request);

// Proctor preparationIdentifiers identifiers = Identifiers.of(

TestType.USER, cookie,TestType.ACCOUNT, accountId

);

Page 95: [@IndeedEng] Managing Experiments and Behavior Dynamically with Proctor

// Proctor preparationIdentifiers identifiers = Identifiers.of(

TestType.USER, trackingCookie,TestType.ACCOUNT, accountId

);

Select Buckets for Opted-In Tests

// Proctor assignmentsProctorResult assignments =

proctor.determineBuckets(identifiers);

Page 96: [@IndeedEng] Managing Experiments and Behavior Dynamically with Proctor

Apply the Experiment

On every request…

1. Select Groups

2. Render the Response3. Log the Action

Page 97: [@IndeedEng] Managing Experiments and Behavior Dynamically with Proctor

Choose behavior for selected bucket

int bgColorBucket;

/* … */

// Choose a background color for templatesif (bgColorBucket == 1) {

// Testmodel.put("buttonBgColor", "#00f");

} else {// Control groupmodel.put("buttonBgColor", "#ccc");

}

Page 98: [@IndeedEng] Managing Experiments and Behavior Dynamically with Proctor

ProctorResult exposes buckets

// Proctor assignmentsProctorResult assignments =

proctor.determineBuckets(identifiers);

// Get selected bucket for this userint bgColorBucket = assignments

// Map<String, TestBucket>: All tests.getBuckets()

// TestBucket: This assignment.get("buttonBgColorTst") // TestBucket

// int: Enumerated ID.getValue();

… verbosely

Page 99: [@IndeedEng] Managing Experiments and Behavior Dynamically with Proctor

"Redundant" names in test spec…

"buttonBgColorTest": {"buckets": {"gray": 0, "blue": 1

}}

Page 100: [@IndeedEng] Managing Experiments and Behavior Dynamically with Proctor

… are used to generate helper methods

// Choose a background color for templatesResumeSearchGroups groups =

new ResumeSearchGroups(assignments);

// Boolean accessors for each test & bucketgroups.isButtonBgColorTstGray();groups.isButtonBgColorTstBlue();

// Enumerated value by test namegroups.getButtonBgColorTstValue();

Page 101: [@IndeedEng] Managing Experiments and Behavior Dynamically with Proctor

Helper designed for use in UI layer

This immutable bean is trivial to:

● Read from JSP/JSF● Read from Templates

○ Freemarker, Velocity, Closure, etc

● Serialize as JSON

Page 102: [@IndeedEng] Managing Experiments and Behavior Dynamically with Proctor

Apply the Experiment

On every request…

1. Select Groups

2. Render the Response

3. Log the Action

Page 103: [@IndeedEng] Managing Experiments and Behavior Dynamically with Proctor

Logging Bucket Assignments

Proctor just selects the buckets.

When and how you log are up to you:

● On related events only● On every event

Page 104: [@IndeedEng] Managing Experiments and Behavior Dynamically with Proctor

Publication

Page 105: [@IndeedEng] Managing Experiments and Behavior Dynamically with Proctor

Test Definitions in Source Control

● No new infrastructure● Lots of desirable features for free

History Diff Access Control

Page 106: [@IndeedEng] Managing Experiments and Behavior Dynamically with Proctor

App Servers

Test Definitions

Proctor Data

App

Publish

Artifact Periodic Refresh

Page 107: [@IndeedEng] Managing Experiments and Behavior Dynamically with Proctor

Individual test changes pushed to a named branch:

Publication is also via Source Control

/trunk

/branches/production

Page 108: [@IndeedEng] Managing Experiments and Behavior Dynamically with Proctor

Overwriting Tests on a Named Branch

Not required to use proctor, but beneficial:

● Same features for free History, Diff, ACL

● No merging● Easy roll-back, roll-forward

Page 109: [@IndeedEng] Managing Experiments and Behavior Dynamically with Proctor

Build Servers

Test Definitions

Test Specifications

Project

Deliverable

App Servers

Publish

Artifact Periodic Refresh

Compile

Deploy

App

Proctor Data

Page 110: [@IndeedEng] Managing Experiments and Behavior Dynamically with Proctor

Beyond the Basics

Page 111: [@IndeedEng] Managing Experiments and Behavior Dynamically with Proctor

Test Segmentation

Page 112: [@IndeedEng] Managing Experiments and Behavior Dynamically with Proctor

Segmentation

Test often apply to only certain users:

● Specific markets

● Specific languages

● Specific devices

Page 113: [@IndeedEng] Managing Experiments and Behavior Dynamically with Proctor

Segmentation through Test Rules

● Test definition allows one optional rule

● A rule is simply a boolean expression

● If the rule passes, the user is assigned to a test bucket

Rules are written in Unified EL

Page 114: [@IndeedEng] Managing Experiments and Behavior Dynamically with Proctor

Simple Things are Simple

{"description": "Button colors","rule": "country == ‘CA’""buckets": […]

}

● No deployment needed

● Changes live within minutes

Page 115: [@IndeedEng] Managing Experiments and Behavior Dynamically with Proctor

Primitive and rich data types

"userAgent.phone || userAgent.tablet"

"userAgent.supports.html5"

"userAgent.supports.geolocation"

"userAgent.supports.fileUpload"

Page 116: [@IndeedEng] Managing Experiments and Behavior Dynamically with Proctor

Commons EL is Easily Extended

JSTL Standard Functions

Custom code

"rule": "fn:endsWith( account.email, '@indeed.com')"

"rule": "proctor:contains(

['US', 'CA'], country)"

Page 117: [@IndeedEng] Managing Experiments and Behavior Dynamically with Proctor

Arbitrary Complexity

Sometimes rules are unavoidably complex:

"Android v2.1+":userAgent.android && ( userAgent.OS.majorVersion gt 2 || ( userAgent.OS.majorVersion == 2

&& userAgent.OS.minorVersion gte 1

))

Page 118: [@IndeedEng] Managing Experiments and Behavior Dynamically with Proctor

What context is available?

So far we've seen:● country● language● userAgent● account

What's the full list of available context variables?

Page 119: [@IndeedEng] Managing Experiments and Behavior Dynamically with Proctor

Context Defined in Test Specification

● Test spec declares available context variables

● This is a contract to provide values at runtime

{"tests": […],"providedContext": {

"country": "String","language": "String""userAgent":

"com.indeed.web.UserAgent"}

}

Page 120: [@IndeedEng] Managing Experiments and Behavior Dynamically with Proctor

// Proctor assignmentsProctorResult assignments =

proctor.determineBuckets(identifiers,country,language,userAgent);

Provided While Determining Buckets

private ResumeSearchProctor proctor;

Also generated from test specification:

Page 121: [@IndeedEng] Managing Experiments and Behavior Dynamically with Proctor

Payloads

Page 122: [@IndeedEng] Managing Experiments and Behavior Dynamically with Proctor

Even Tiny Changes Need Deploys

// Choose a background color for templatesif (bgColorBucket == 1) {

// Testmodel.put("btnBgcolor", "#00f");

} else {// Control groupmodel.put("btnBgcolor", "#ccc");

}

Page 123: [@IndeedEng] Managing Experiments and Behavior Dynamically with Proctor

Many tests have no behavioral change:● CSS Colors

● Display Text

● Algorithm Weights

Some Tests Just Vary Data

Page 124: [@IndeedEng] Managing Experiments and Behavior Dynamically with Proctor

Payloads

● Values added for each bucket in a test

● Proctor verifies payloads are "all or none"

Control: Gray Test: Blue

Page 125: [@IndeedEng] Managing Experiments and Behavior Dynamically with Proctor

Payloads

● Values added for each bucket in a test

● Proctor verifies payloads are "all or none"

Control: Gray Test: Blue

"#ccc" "#00f"

Page 126: [@IndeedEng] Managing Experiments and Behavior Dynamically with Proctor

Part of Test Definition

"buckets": [{"id": 0, "name": "gray","description": "Control group","payload": {"stringValue": "#ccc"

}}, …]

● No deployment needed

● Changes live within minutes

Page 127: [@IndeedEng] Managing Experiments and Behavior Dynamically with Proctor

Declared in Project Test Specification

● Type definition only

● Must match test definition

"buttonBgColorTst": {"buckets": […],"payload": {"type": "stringValue"

}}

Page 128: [@IndeedEng] Managing Experiments and Behavior Dynamically with Proctor

Cleaner Code, Only Data Deploy

// Choose a background colormodel.put("btnBgcolor", groups.getButtonBgColorTstPayload()

);

Page 129: [@IndeedEng] Managing Experiments and Behavior Dynamically with Proctor

Cross-Product Tests

Page 130: [@IndeedEng] Managing Experiments and Behavior Dynamically with Proctor

Cross-Product Tests

Many flavors of cross-product test, including

● Peer webapps

● Client / Service

● Mobile Native / Web

Page 131: [@IndeedEng] Managing Experiments and Behavior Dynamically with Proctor

Proctor offers an interesting alternative

Cross-Product Tests

Even more ways to coordinate tests

● Tracking parameters on links, requests

● Service response metadata

● Different service calls

Page 132: [@IndeedEng] Managing Experiments and Behavior Dynamically with Proctor

Two products can share test groups

As long as both products

● Share the test’s identifier● Provide the context variables it uses

Deterministic selection guarantees identical bucket assignment.

Page 133: [@IndeedEng] Managing Experiments and Behavior Dynamically with Proctor

Evolving Tests

Page 134: [@IndeedEng] Managing Experiments and Behavior Dynamically with Proctor

Evolving Tests

testcontrol

Page 135: [@IndeedEng] Managing Experiments and Behavior Dynamically with Proctor

Evolving Tests

testcontrol (inactive)

10%

Page 136: [@IndeedEng] Managing Experiments and Behavior Dynamically with Proctor

control

Changed allocations, not ID mapping

testOOPS!

● Inconsistent experience● Polluted results

Page 137: [@IndeedEng] Managing Experiments and Behavior Dynamically with Proctor

Evolving Tests Smoothly

[ 10%, 10%]

testcontrol (inactive)

[ 10%, 10%, 80% ]

Page 138: [@IndeedEng] Managing Experiments and Behavior Dynamically with Proctor

Evolving Tests Smoothly

[ 10%, 10%, 80% ]

[ 10%, 10%, 40%, 40%]

testcontrol (inactive)

testcontrol testcontrol

Page 139: [@IndeedEng] Managing Experiments and Behavior Dynamically with Proctor

Evolving Tests Smoothly

[ 10%, 80%, 10% ]

[ 50%, 50% ]

testcontrol (inactive)

control test

Page 140: [@IndeedEng] Managing Experiments and Behavior Dynamically with Proctor

Evolving Tests… Turbulently

hash ( uid + test.salt ) => bucket

Any ID:

testcontrol

Test range:

test

1te

st1

After re-salt:

Page 141: [@IndeedEng] Managing Experiments and Behavior Dynamically with Proctor

Contextual Sampling

Page 142: [@IndeedEng] Managing Experiments and Behavior Dynamically with Proctor

Contextual Allocation

testcontrol (inactive)

10% (US):

50% (Rest of World):testcontrol

testcontrol

20% (CA):(inactive)

Page 143: [@IndeedEng] Managing Experiments and Behavior Dynamically with Proctor

Allocations

Each test definition ● has one or more allocations

Each allocation● has a rule and ranges totaling 1.0● except the last, which has no rule.

Page 144: [@IndeedEng] Managing Experiments and Behavior Dynamically with Proctor

Allocation Rules

● Use Unified EL, same as test rules.

● Use the same context variables as test rules.

● Choose the first matching allocation.

Page 145: [@IndeedEng] Managing Experiments and Behavior Dynamically with Proctor

Allocations in the Test Definition{ "description": "Button colors","type": "USER","salt": "buttonBgColorTst","buckets": [ … ],"allocations": [{"rule": "country == 'US'","ranges": [ … ]

}, {"ranges": [ … ]

}]}

Page 146: [@IndeedEng] Managing Experiments and Behavior Dynamically with Proctor

Pre-Production

Page 147: [@IndeedEng] Managing Experiments and Behavior Dynamically with Proctor

Environments

Local

Integration

QA

Production

commit

push

push

Page 148: [@IndeedEng] Managing Experiments and Behavior Dynamically with Proctor

Show test matrix

/private/showTestMatrix

Page 149: [@IndeedEng] Managing Experiments and Behavior Dynamically with Proctor

Show test bucket assignments

/private/showGroups/private/showGroups

Page 150: [@IndeedEng] Managing Experiments and Behavior Dynamically with Proctor

Privileged users can force assignments

Page 151: [@IndeedEng] Managing Experiments and Behavior Dynamically with Proctor

Privileged users can force assignments

?prforceGroups=buttonColorTst1

Page 152: [@IndeedEng] Managing Experiments and Behavior Dynamically with Proctor

Beyond A/B TestingProctor Patterns for Managing Behavior

Page 153: [@IndeedEng] Managing Experiments and Behavior Dynamically with Proctor

Kill SwitchWhen ● New Feature

How● 'Active' bucket @ 100%

Page 154: [@IndeedEng] Managing Experiments and Behavior Dynamically with Proctor

Phased RolloutWhen ● Experimental Feature

How● 'Active' bucket @ 0%● 'Active' → 1% → 5% → 100%

Page 155: [@IndeedEng] Managing Experiments and Behavior Dynamically with Proctor

When ● Downsampling

○ trace logging○ survey

How● 'Active' bucket @ 0%● 'Active' → 1% → 10% → 5% → ??

Throttle

Page 156: [@IndeedEng] Managing Experiments and Behavior Dynamically with Proctor

Feature TogglesWhen ● Localized Behavior● Device-Specific Behavior● Logged-in, w/ Resume, etc.

How● Multiple Allocations ● Targeted Rules

Page 157: [@IndeedEng] Managing Experiments and Behavior Dynamically with Proctor

Dark DeploysWhen ● Partial Implementations● Additional QA is needed

How● 'Active' bucket @ 0%● 'Active' → 100%

Page 158: [@IndeedEng] Managing Experiments and Behavior Dynamically with Proctor

When ● Dependencies between products

○ Resume Wizard feature

How● 'Active' bucket at 0%● Resume Wizard allocation: → 100%● Home page promo allocation: → 100%

Cross-Product Coordination

Page 159: [@IndeedEng] Managing Experiments and Behavior Dynamically with Proctor

Pre-Proctor Tests

Page 160: [@IndeedEng] Managing Experiments and Behavior Dynamically with Proctor

Post-Proctor Tests

Proctor

42

103

Page 161: [@IndeedEng] Managing Experiments and Behavior Dynamically with Proctor

Post-Proctor Tests + Toggles

Proctor

42

10

103

65

Page 162: [@IndeedEng] Managing Experiments and Behavior Dynamically with Proctor

Proctor WebappA/B Test Change Management

(Coming Soon to github)

Page 163: [@IndeedEng] Managing Experiments and Behavior Dynamically with Proctor
Page 164: [@IndeedEng] Managing Experiments and Behavior Dynamically with Proctor

Proctor Webapp

Page 165: [@IndeedEng] Managing Experiments and Behavior Dynamically with Proctor

Proctor Webapp

Page 166: [@IndeedEng] Managing Experiments and Behavior Dynamically with Proctor

Proctor Webapp

Page 167: [@IndeedEng] Managing Experiments and Behavior Dynamically with Proctor

Proctor Webapp

Page 168: [@IndeedEng] Managing Experiments and Behavior Dynamically with Proctor

Building On Proctor(Not Open Source)

Page 169: [@IndeedEng] Managing Experiments and Behavior Dynamically with Proctor
Page 170: [@IndeedEng] Managing Experiments and Behavior Dynamically with Proctor
Page 171: [@IndeedEng] Managing Experiments and Behavior Dynamically with Proctor

Description: Group 0: control - Job alert label: Save Alert (control) Group 1: labelSubscribe - Job alert label: Subscribe Group 2: labelSignUp - Job alert label: Sign up Group 3: labelGetJobs - Job alert label: Get jobs Group 4: labelSendMeNewJobs - Job alert label: Send me new jobs Group 5: labelActivate - Job alert label: Activate Group 6: labelSave - Job alert label: Save

Page 172: [@IndeedEng] Managing Experiments and Behavior Dynamically with Proctor

History:

jack @ 2013-03-12 (r203267): Promoting jasxjabtnlbltst (trunk r203089) to

production JASX-11365: jasxjabtnlbltst disabled

ketan @ 2012-12-11 (r190675): merged r190418: JASX-10663: Stop

jasxjabtnlbltst in all languages except nl

will @ 2012-11-29 (r188801): merged r187452: JASX-10457: exclude US from

jasxjabtnlbltst

ketan @ 2012-10-25 (r182881): merged r182688: JASX-10234 - Adding new

langauges to job alert button label test

ketan @ 2012-10-25 (r182876): merged r181938: JASX-10234 - Adding test

definition and allocations for job alert button label test

Page 173: [@IndeedEng] Managing Experiments and Behavior Dynamically with Proctor

DEMOGet out your Phones and Tablets

Page 174: [@IndeedEng] Managing Experiments and Behavior Dynamically with Proctor

http://go.indeed.com/demo

Simple: test different background colors 25% 25%

25%25%

50%

Page 175: [@IndeedEng] Managing Experiments and Behavior Dynamically with Proctor

http://go.indeed.com/demo

Let’s increase our bucket size...

50%

50%

Page 176: [@IndeedEng] Managing Experiments and Behavior Dynamically with Proctor

http://go.indeed.com/demo

We have a winner! 50%

100%

Page 177: [@IndeedEng] Managing Experiments and Behavior Dynamically with Proctor

http://go.indeed.com/demo

Let’s do something wacky!

Android >= 4 iOS >= 7

iOSAndroid

Page 178: [@IndeedEng] Managing Experiments and Behavior Dynamically with Proctor

http://go.indeed.com/demo

Also a reference implementation

Running on heroku -- feel free to clone!http://indeedeng-hello-proctor.herokuapp.com

Source:github.com/indeedeng/proctor-demo

Page 180: [@IndeedEng] Managing Experiments and Behavior Dynamically with Proctor

Next @IndeedEng Talk

BoxcarSelf-balancing distributed services

Wednesday, October 30R.B. Boyer