At Artsy Engineering we encourage a culture of experimentation with something called labs.

A new feature released into production is usually only turned on for a handful of users. We get feedback from our own team and a tiny group of early adopters, iterate, fix bugs, toss failed experiments and work on promoting complete, well behaved features to all users. The labs infrastructure gives us a chance to sleep on an idea and polish details. It also allows us to make progress continuously and flip a switch on the very last day.

My favorite labs features push our collective imagination and give birth to productive brainstorms around coffee at a popular startup hangout around the corner from our Manhattan office. But the team's favorite labs are, by far, those that ship as easter eggs. These are fun and sometimes useful features that don't make much business sense. So, before I explain our rudimentary labs system, I want to invite you to our easter egg hunt. Check out https://artsy.net/humans.txt for instructions.

Our labs infrastructure is rather straightforward. A lab feature data model is pretty boring, with the exception of a created_by field. Each such lab feature belongs to an engineer and you have to nurture your feature and fight for it to meet the production bar!

app/models/lab_feature.rb
1
2
3
4
5
6
7
class LabFeature
  include Mongoid::Document
  include Mongoid::Timestamps

  field :name
  field :created_by
end

You can enable and disable a lab feature for a given user.

app/models/user.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class User
  references_and_referenced_in_many :lab_features

  def enable_lab_feature!(feature)
    lab_features.push(feature) unless lab_features.member?(feature)
    save!
  end

  def disable_lab_feature!(feature)
    lab_features.delete(feature)
    save!
  end

  def lab_feature_enabled?(feature)
    lab_features.member?(feature)
  end
end

In Ruby, we check whether the user has a lab with lab_feature_enabled?. In JavaScript, we return the lab features in a Backbone.js collection and check for the same.

app/coffeescripts/models/user.coffee
1
2
3
4
class App.Models.CurrentUser extends Backbone.Model

  hasLabFeature: (feature_name) ->
    $.inArray(feature_name, @get('lab_features')) >= 0

We also have a bit of UI and an API to let you turn a lab feature on and off when you're part of our labs program. The program itself is also a lab feature!

Lab features can be retired after the code is promoted to all users or deleted.

app/models/lab_feature.rb
1
2
3
4
5
6
7
8
class LabFeature
  def retire!
    User.all.each do |u|
      u.disable_lab_feature!(self)
    end
    destroy
  end
end

This "system" is super simple. I encourage you to think more in terms of experiments or labs - it helped us foster a culture of innovation, tremendously reduced risk of catastrophic failures, and, because anyone can push anything into labs at any time, removed the unnecessary discussions around whether an idea is worthy of an implementation at all.

Categories: experiments, fun, programming


Comments