%!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