Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Feature Flags

Feature Flags

A 15 minute presentation given at PyCon 2014 as part of the Advanced Django Patterns workshop http://lanyrd.com/2014/pycon/scxqhp/ describing feature flags, how we rolled our own at Lanyrd and how Eventbrite use Gargoyle.

E172168287724cd3051588354ded616b?s=128

Simon Willison

April 10, 2014
Tweet

Transcript

  1. Feature Flags Simon Willison, @simonw ! PyCon 2014

  2. “Release early, release often”

  3. None
  4. https://www.flickr.com/photos/dottiemae/5236273049/

  5. A way of exposing features to a sub-set of your

    userbase
  6. Decouple deployment from release

  7. (+ risk-free instant rollback)

  8. FEATURE_FLAGS = {! 'mapbox': 'Uses MapBox maps rather than Google

    Maps',! }!
  9. class FeatureFlag(Model):! slug = SlugField(unique = True)! description = CharField(max_length

    = 140)! enabled_for_all = BooleanField(default = False)
  10. class FeatureFlag(Model):! slug = SlugField(unique = True)! description = CharField(max_length

    = 140)! enabled_for_all = BooleanField(default = False)! users = ManyToManyField(User)!
  11. class FeatureFlag(Model):! slug = SlugField(unique = True)! description = CharField(max_length

    = 140)! enabled_for_all = BooleanField(default = False)! users = ManyToManyField(User)! groups = ManyToManyField(Group)
  12. def is_enabled(self, user):! return (! self.enabled_for_all or! self.users.filter(pk = user.pk).exists()

    or! self.groups.filter(users__pk = user.pk).exists()! )!
  13. @flag_required('topic_tracking')! def topic_track(request, slug):! # ... view code ... !

  14. if user.has_flag('topic_tracking'):! # ...!

  15. {% flag new_eventbrite %}! <p>Lanyrd is an <img src="/eb.png" alt="Eventbrite">

    company</p>! {% endflag %}!
  16. {% flagactive login_facebook %}(alpha-only){% endflagactive %}

  17. None
  18. In read_only_mode • Prevent logged-in user actions • Auth middleware

    ignores user cookie • Mobile app APIs ignore user token • Shows the banner and hide the “sign in” link
  19. MySQL on EC2 PostgreSQL on SoftLayer with no downtime

  20. Feature flags at Eventbrite

  21. Gargoyle

  22. • User / Staff • Event • Organizer • API

    key • Country • IP address (or range) • eventbrite.com v.s. .de v.s. .fr
  23. class RequestCountry(ConditionSet):! country = String(label='Country')! def can_execute(self, instance):! return isinstance(instance,

    (HttpRequest,))! ! def get_field_value(self, request, field_name):! if field_name == 'country':! return getattr(request, 'country')! ! gargoyle.register(RequestCountry())
  24. Gotchas • Unexpected flag combinations • Old feature flag code

    • Performance!
  25. Gargoyle performance • Switch = DB row with JSON blob

    of conditions • Caches switches in local memory AND remote cache • At Eventbrite, we run memcached on every frontend server to reduce network traffic
  26. Meanwhile, at Facebook…

  27. Meanwhile, at Facebook… 500M+ gatekeeper checks/second - back in 2012!

  28. https://www.flickr.com/photos/capcase/4970062156/

  29. • Use feature flags, not long-lived branches! • The ROI

    on feature flags is ridiculous • Try Gargoyle (or Gutter), or roll your own