%!PS-Adobe-3.0 %%DocumentMedia: SLIDE 842 595 0 () () %%EndComments %%BeginDefaults %%PageMedia: SLIDE %%EndDefaults << /PageSize [842 595] /ImagingBBox null >> setpagedevice /reencode { exch findfont dup length dict begin { 1 index /FID ne { def } { pop pop } ifelse } forall /Encoding ISOLatin1Encoding def currentdict end definefont pop } def /Times /Times reencode /Courier /Courier reencode /Times-Italic /Times-Italic reencode /Helvetica /Helvetica reencode /headerheight 75 def /frontfontsz 60 def /authorfontsz 40 def /titlefontsz 40 def /mainfontsz 30 def /codefontsz 18 def /tinyfontsz 18 def /titlefont /Helvetica findfont titlefontsz scalefont def /mainfont /Courier findfont mainfontsz scalefont def /codefont /Courier findfont codefontsz scalefont def /tinyfont /Times findfont tinyfontsz scalefont def /frontfont /Helvetica findfont frontfontsz scalefont def /authorfont /Times-Italic findfont authorfontsz scalefont def /authorfonttwo /Times findfont authorfontsz scalefont def /pagewidth 842 def /pageheight 595 def /leftmargin 30 def /topmargin 595 def /pad 10 def /titlefonth titlefontsz pad add def /mainfonth mainfontsz pad add def /codefonth codefontsz pad add def /tinyfonth tinyfontsz pad add def /frontfonth frontfontsz pad add def /authorfonth authorfontsz pad add def /headermargin pageheight headerheight titlefonth sub 2 div titlefontsz add sub def /rightmargin pagewidth leftmargin sub def /tbtop topmargin def /ypos topmargin def /xcur { currentpoint pop } def /ycur { currentpoint exch pop } def /wordbreak ( ) def /linewrap { /proc exch def /linelength exch def /textstring exch def /breakwidth wordbreak stringwidth pop def /curwidth 0 def /lastwordbreak 0 def /startchar 0 def /restoftext textstring def { restoftext wordbreak search { /nextword exch def pop /restoftext exch def /wordwidth nextword stringwidth pop def curwidth wordwidth add linelength gt { textstring startchar lastwordbreak startchar sub getinterval proc /startchar lastwordbreak def /curwidth wordwidth breakwidth add def } { /curwidth curwidth wordwidth add breakwidth add def } ifelse /lastwordbreak lastwordbreak nextword length add 1 add def } { pop exit } ifelse } loop /lastchar textstring length def textstring startchar lastchar startchar sub getinterval proc } def /line { 0 0 0 setrgbcolor 0.5 setlinewidth leftmargin ypos moveto rightmargin ypos lineto stroke } def /center { dup /str exch def /sw str stringwidth pop def /xpos pagewidth sw sub 2 div xcur sub def xpos 0 rmoveto } def /objcenter { pagewidth exch sub 2 div 0 translate } def /s { /tbtop topmargin def /ypos topmargin def 1 1 1 setrgbcolor 0 setlinewidth newpath 0 pageheight moveto pagewidth pageheight lineto pagewidth 0 lineto 0 0 lineto closepath fill stroke } def /l { /h exch def /ypos ypos h sub def leftmargin ypos moveto } def /title { frontfonth l frontfont setfont 0.5 0.5 0.9 setrgbcolor { pagewidth leftmargin 2 mul sub } { frontfonth l center show } linewrap frontfonth 2 div l frontfonth l } def /author { authorfont setfont 0 0 0 setrgbcolor { pagewidth leftmargin 2 mul sub } { authorfonth l center show } linewrap } def /authortwo { authorfonttwo setfont 0 0 0 setrgbcolor { pagewidth leftmargin 2 mul sub } { authorfonth l center show } linewrap } def /header { /ypos pageheight headerheight sub def 0 0 0 setrgbcolor 0 setlinewidth newpath 0 pageheight moveto pagewidth pageheight lineto pagewidth ypos lineto 0 ypos lineto closepath fill stroke leftmargin headermargin moveto titlefont setfont 0.5 0.5 0.9 setrgbcolor center show leftmargin ypos moveto } def /n { mainfont setfont 0 0 0 setrgbcolor { pagewidth leftmargin 2 mul sub } { mainfonth l show } linewrap } def /cn { codefont setfont 0 0 0 setrgbcolor { pagewidth leftmargin 2 mul sub } { codefonth l show } linewrap } def /tn { tinyfont setfont 0 0 0 setrgbcolor { pagewidth leftmargin 2 mul sub } { tinyfonth l show } linewrap } def /is { /level1 save def /showpage {} def } def /ie { level1 restore } def /bs { /tbtop ypos def } def /be { /tm tbtop pad sub def /bm ypos pad sub def newpath leftmargin 10 sub tm moveto rightmargin tm lineto rightmargin bm lineto leftmargin 10 sub bm lineto closepath 0 0 0 setrgbcolor 0.5 setlinewidth stroke } def showpage %%Page: 1 1 s ( Rollout, feature flag, experiment, operational toggle) title (Different use cases for backend, frontend and mobile ) authortwo showpage %%Page: 2 2 s () n () n () n ( "Feature flags" tend to come up when talking about continuous deployment) title showpage %%Page: 3 3 s () n () n () n () n (CI: continuous integration) authortwo () n (CD: continuous delivery) authortwo () n (CD: continuous deployment) authortwo showpage %%Page: 4 4 s ( Types) header () n () n () n (1. rollout) n (2. feature flag) n (3. experiment) n (4. operational toggle) n showpage %%Page: 5 5 s ( Rollout) header ( For *rolling out* a new version of software) title (Short-lived using percentages) n (- a new deployment of kubernetes) n (- new APK released to the Play Store) n showpage %%Page: 6 6 s ( Feature flag) header ( For turning a feature *on* or *off* ) title (Medium-lived using allow list, A/B test, percentage, app version, etc.) n (- :new-chargeback-flow) n (- :new-debit-card-activation-screen) n showpage %%Page: 7 7 s ( Experiment) header ( For analysing behaviour) title (Medium-lived using allow list and A/B test) n (- :debit-withdrawal-test) n showpage %%Page: 8 8 s ( Operational toggle) header ( For disabling features in #crash-like situations) title (Long-lived using percentage) n (- :bank-barcode-payment) n (- :savings-bank-barcode-query-provider) n showpage %%Page: 9 9 s () n () n (We know know about the types) authortwo ( But they have different relevance for backend, frontend and mobile) title showpage %%Page: 10 10 s ( backend) header () n () n (1. rollout: k8s blue/green, canary and ~common-rollout~ common-xp) n (2. feature flag: ~common-rollout~ common-xp and datasets) n (3. experiment: common-xp) n (4. operational toggle: ~common-rollout~ common-xp ) n showpage %%Page: 11 11 s ( frontend) header () n () n (1. rollout: CDN and page refreshes) n (2. feature flag: percentages and maybe IPs \(no :customer/id on the website\)) n (3. experiment: via dynamic backend control) n (4. operational toggle: via dynamic backend control ) n showpage %%Page: 12 12 s ( backend) header () n () n (1. rollout: app stores) n (2. feature flag: via dynamic backend control) n (3. experiment: via dynamic backend control) n (4. operational toggle: via dynamic backend control ) n showpage %%Page: 13 13 s () n () n (Key differentiator is) authortwo ( how much *control* we have over the environment) title showpage %%Page: 14 14 s ( backend) header ( full control) title showpage %%Page: 15 15 s ( frontend) header ( partial control) title (We choose when to make a new version available ) n showpage %%Page: 16 16 s ( mobile) header ( very limited control) title (- app stores can restrict updates \(worse for iOS\)) n (- customers still have to download new versions ) n showpage %%Page: 17 17 s ( Costs) title (- more complex code) n (- compatibility with old app versions) n (- nesting is exponential) n showpage %%Page: 18 18 s ( Benefits) title (- dynamicity) n showpage %%Page: 19 19 s ( weighting costs × benefits) header ( The less control we have, the more we value dynamicity ) title showpage %%Page: 20 20 s ( weighting costs × benefits) header () n () n () n (- backend: sometimes worth the cost) n (- frontend: almost always worth the cost) n (- mobile: *always* worth the cost) n showpage %%Page: 21 21 s () n () n () n ( Best practices) title showpage %%Page: 22 22 s ( dynamic content > feature flag) title (Always true for mobile, almost always for frontend ) n showpage %%Page: 23 23 s ( Use :include-list for named groups ) title (Always true for backend, frontend and mobile ) n bs ({:rules) cn ( #{{:types :include-list) cn ( :content {:filename "debit-team-members.txt"}}}}) cn be showpage %%Page: 24 24 s ( Always use :app-version) title (Only for mobile) n bs ({:rules) cn ( #{{:types :app-version) cn ( :content {:min-version #{{:platform :android) cn ( :code 1000000}) cn ( {:platform :ios) cn ( :code 2000000}}}}}}) cn be showpage %%Page: 25 25 s ( Extend ~common-rollout~ common-xp if required) title (That's how :include-list, :app-version, etc. were born) n showpage %%Page: 26 26 s ( Beware of many nested feature flags) title (True for backend, frontend and mobile) n showpage %%Page: 27 27 s ( Don't delete app-facing feature flags) title (True for mobile) n showpage %%Page: 28 28 s () n () n () n ( Include a feature flag on the whiteboarding phase) title showpage %%Page: 29 29 s () n () n () n ( Include deleting/retiring the feature flag at the end) title showpage %%Page: 30 30 s ( Avoid renaming a feature flag) title (Use :app-version with :min-version instead) n showpage %%Page: 31 31 s () n () n () n ( And most importantly...) title showpage %%Page: 32 32 s ( *Always* rely on a feature flag on the app) title (Never do a hotfix, avoid expedited releases at all costs) n showpage %%Page: 33 33 s ( References) header () n (1. "Feature Toggles \(aka Feature Flags\)", by Pete Hodgson) n (2. "Continuous integration vs. delivery vs. deployment", by Sten Pittet) n (3. Accelerate, by N. Forsgren, J. Humble and G. Kim) n (4. these slides: euandre.org/slide/) n (5. prose version of this presentation) n (6. view source) n showpage %%EOF