aboutsummaryrefslogblamecommitdiff
path: root/locale/pt/LC_MESSAGES/_articles/2020-10-19-feature-flags-differences-between-backend-frontend-and-mobile.po
blob: 89911cacc2cd2a0be462588f1a715fc81f38a21a (plain) (tree)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406




         
















































































































































































































































































































































































































                                                                                          

















                                                            



















                                                                                 
#
msgid ""
msgstr ""

msgid ""
"*This article is derived from a [presentation][presentation] on the same "
"subject.*"
msgstr ""

msgid ""
"When discussing about feature flags, I find that their costs and benefits "
"are often well exposed and addressed. Online articles like \"[Feature Toggle"
" (aka Feature Flags)][feature-flags-article]\" do a great job of explaining "
"them in detail, giving great general guidance of how to apply techniques to "
"adopt it."
msgstr ""

msgid ""
"However the weight of those costs and benefits apply differently on backend,"
" frontend or mobile, and those differences aren't covered. In fact, many of "
"them stop making sense, or the decision of adopting a feature flag or not "
"may change depending on the environment."
msgstr ""

msgid ""
"In this article I try to make the distinction between environments and how "
"feature flags apply to them, with some final best practices I've acquired "
"when using them in production."
msgstr ""

msgid ""
"[presentation]: {% link _slides/2020-10-19-rollout-feature-flag-experiment-"
"operational-toggle.slides %} [feature-flags-article]: "
"https://martinfowler.com/articles/feature-toggles.html"
msgstr ""

msgid "Why feature flags"
msgstr ""

msgid ""
"Feature flags in general tend to be cited on the context of [continuous "
"deployment](https://www.atlassian.com/continuous-"
"delivery/principles/continuous-integration-vs-delivery-vs-deployment):"
msgstr ""

msgid "A: With continuous deployment, you deploy to production automatically"
msgstr ""

msgid "B: But how do I handle deployment failures, partial features, *etc.*?"
msgstr ""

msgid ""
"A: With techniques like canary, monitoring and alarms, feature flags, *etc.*"
msgstr ""

msgid ""
"Though adopting continuous deployment doesn't force you to use feature "
"flags, it creates a demand for it. The inverse is also true: using feature "
"flags on the code points you more obviously to continuous deployment. Take "
"the following code sample for example, that we will reference later on the "
"article:"
msgstr ""

msgid ""
"While being developed, being tested for suitability or something similar, "
"`notifyListeners()` may not be included in the code at once. So instead of "
"keeping it on a separate, long-lived branch, a feature flag can decide when "
"the new, partially implemented function will be called:"
msgstr ""

msgid ""
"This allows your code to include `notifyListeners()`, and decide when to "
"call it at runtime. For the price of extra things around the code, you get "
"more dynamicity."
msgstr ""

msgid ""
"So the fundamental question to ask yourself when considering adding a "
"feature flag should be:"
msgstr ""

msgid "Am I willing to pay with code complexity to get dynamicity?"
msgstr ""

msgid ""
"It is true that you can make the management of feature flags as "
"straightforward as possible, but having no feature flags is simpler than "
"having any. What you get in return is the ability to parameterize the "
"behaviour of the application at runtime, without doing any code changes."
msgstr ""

msgid ""
"Sometimes this added complexity may tilt the balance towards not using a "
"feature flag, and sometimes the flexibility of changing behaviour at runtime"
" is absolutely worth the added complexity. This can vary a lot by code base,"
" feature, but fundamentally by environment: its much cheaper to deploy a new"
" version of a service than to release a new version of an app."
msgstr ""

msgid ""
"So the question of which environment is being targeted is key when reasoning"
" about costs and benefits of feature flags."
msgstr ""

msgid "Control over the environment"
msgstr ""

msgid ""
"The key differentiator that makes the trade-offs apply differently is how "
"much control you have over the environment."
msgstr ""

msgid ""
"When running a **backend** service, you usually are paying for the servers "
"themselves, and can tweak them as you wish. This means you have full control"
" do to code changes as you wish. Not only that, you decide when to do it, "
"and for how long the transition will last."
msgstr ""

msgid ""
"On the **frontend** you have less control: even though you can choose to "
"make a new version available any time you wish, you can't force[^force] "
"clients to immediately switch to the new version. That means that a) clients"
" could skip upgrades at any time and b) you always have to keep backward and"
" forward compatibility in mind."
msgstr ""

msgid ""
"Even though I'm mentioning frontend directly, it applies to other "
"environment with similar characteristics: desktop applications, command-line"
" programs, *etc*."
msgstr ""

msgid ""
"On **mobile** you have even less control: app stores need to allow your app "
"to be updated, which could bite you when least desired. Theoretically you "
"could make you APK available on third party stores like "
"[F-Droid](https://f-droid.org/), or even make the APK itself available for "
"direct download, which would give you the same characteristics of a frontend"
" application, but that happens less often."
msgstr ""

msgid ""
"On iOS you can't even do that. You have to get Apple's blessing on every "
"single update. Even though we already know that is a [bad "
"idea](http://www.paulgraham.com/apple.html) for over a decade now, there "
"isn't a way around it. This is where you have the least control."
msgstr ""

msgid ""
"In practice, the amount of control you have will change how much you value "
"dynamicity: the less control you have, the more valuable it is. In other "
"words, having a dynamic flag on the backend may or may not be worth it since"
" you could always update the code immediately after, but on iOS it is "
"basically always worth it."
msgstr ""

msgid ""
"[^force]: Technically you could force a reload with JavaScript using "
"`window.location.reload()`, but that not only is invasive and impolite, but "
"also gives you the illusion that you have control over the client when you "
"actually don't: clients with disabled JavaScript would be immune to such "
"tactics."
msgstr ""

msgid "Rollout"
msgstr ""

msgid "A rollout is used to *roll out* a new version of software."
msgstr ""

msgid ""
"They are usually short-lived, being relevant as long as the new code is "
"being deployed. The most common rule is percentages."
msgstr ""

msgid ""
"On the **backend**, it is common to find it on the deployment infrastructure"
" itself, like canary servers, blue/green deployments, [a kubernetes "
"deployment "
"rollout](https://kubernetes.io/docs/concepts/workloads/controllers/deployment/#creating-"
"a-deployment), *etc*. You could do those manually, by having a dynamic "
"control on the code itself, but rollbacks are cheap enough that people "
"usually do a normal deployment and just give some extra attention to the "
"metrics dashboard."
msgstr ""

msgid ""
"Any time you see a blue/green deployment, there is a rollout happening: most"
" likely a load balancer is starting to direct traffic to the new server, "
"until reaching 100% of the traffic. Effectively, that is a rollout."
msgstr ""

msgid ""
"On the **frontend**, you can selectively pick which user's will be able to "
"download the new version of a page. You could use geographical region, IP, "
"cookie or something similar to make this decision."
msgstr ""

msgid ""
"CDN propagation delays and people not refreshing their web pages are also "
"rollouts by themselves, since old and new versions of the software will "
"coexist."
msgstr ""

msgid ""
"On **mobile**, the Play Store allows you to perform fine-grained [staged "
"rollouts](https://support.google.com/googleplay/android-"
"developer/answer/6346149?hl=en), and the App Store allows you to perform "
"limited [phased releases](https://help.apple.com/app-store-"
"connect/#/dev3d65fcee1)."
msgstr ""

msgid ""
"Both for Android and iOS, the user plays the role of making the download."
msgstr ""

msgid ""
"In summary: since you control the servers on the backend, you can do "
"rollouts at will, and those are often found automated away in base "
"infrastructure. On the frontend and on mobile, there are ways to make new "
"versions available, but users may not download them immediately, and many "
"different versions of the software end up coexisting."
msgstr ""

msgid "Feature flag"
msgstr ""

msgid ""
"A feature flag is a *flag* that tells the application on runtime to turn on "
"or off a given *feature*. That means that the actual production code will "
"have more than one possible code paths to go through, and that a new version"
" of a feature coexists with the old version. The feature flag tells which "
"part of the code to go through."
msgstr ""

msgid ""
"They are usually medium-lived, being relevant as long as the new code is "
"being developed. The most common rules are percentages, allow/deny lists, "
"A/B groups and client version."
msgstr ""

msgid ""
"On the **backend**, those are useful for things that have a long development"
" cycle, or that needs to done by steps. Consider loading the feature flag "
"rules in memory when the application starts, so that you avoid querying a "
"database or an external service for applying a feature flag rule and avoid "
"flakiness on the result due to intermittent network failures."
msgstr ""

msgid ""
"Since on the **frontend** you don't control when to update the client "
"software, you're left with applying the feature flag rule on the server, and"
" exposing the value through an API for maximum dynamicity. This could be in "
"the frontend code itself, and fallback to a \"just refresh the page\"/\"just"
" update to the latest version\" strategy for less dynamic scenarios."
msgstr ""

msgid ""
"On **mobile** you can't even rely on a \"just update to the latest version\""
" strategy, since the code for the app could be updated to a new feature and "
"be blocked on the store. Those cases aren't recurrent, but you should always"
" assume the store will deny updates on critical moments so you don't find "
"yourself with no cards to play. That means the only control you actually "
"have is via the backend, by parameterizing the runtime of the application "
"using the API. In practice, you should always have a feature flag to control"
" any relevant piece of code. There is no such thing as \"too small code "
"change for a feature flag\". What you should ask yourself is:"
msgstr ""

msgid ""
"If the code I'm writing breaks and stays broken for around a month, do I "
"care?"
msgstr ""

msgid ""
"If you're doing an experimental screen, or something that will have a very "
"small impact you might answer \"no\" to the above question. For everything "
"else, the answer will be \"yes\": bug fixes, layout changes, refactoring, "
"new screen, filesystem/database changes, *etc*."
msgstr ""

msgid "Experiment"
msgstr ""

msgid ""
"An experiment is a feature flag where you care about analytical value of the"
" flag, and how it might impact user's behaviour. A feature flag with "
"analytics."
msgstr ""

msgid ""
"They are also usually medium-lived, being relevant as long as the new code "
"is being developed. The most common rule is A/B test."
msgstr ""

msgid ""
"On the **backend**, an experiment rely on an analytical environment that "
"will pick the A/B test groups and distributions, which means those can't be "
"held in memory easily. That also means that you'll need a fallback value in "
"case fetching the group for a given customer fails."
msgstr ""

msgid ""
"On the **frontend** and on **mobile** they are no different from feature "
"flags."
msgstr ""

msgid "Operational toggle"
msgstr ""

msgid ""
"An operational toggle is like a system-level manual circuit breaker, where "
"you turn on/off a feature, fail over the load to a different server, *etc*. "
"They are useful switches to have during an incident."
msgstr ""

msgid ""
"They are usually long-lived, being relevant as long as the code is in "
"production. The most common rule is percentages."
msgstr ""

msgid ""
"They can be feature flags that are promoted to operational toggles on the "
"**backend**, or may be purposefully put in place preventively or after a "
"postmortem analysis."
msgstr ""

msgid ""
"On the **frontend** and on **mobile** they are similar to feature flags, "
"where the \"feature\" is being turned on and off, and the client interprets "
"this value to show if the \"feature\" is available or unavailable."
msgstr ""

msgid "Best practices"
msgstr ""

msgid "Prefer dynamic content"
msgstr ""

msgid ""
"Even though feature flags give you more dynamicity, they're still somewhat "
"manual: you have to create one for a specific feature and change it by hand."
msgstr ""

msgid ""
"If you find yourself manually updating a feature flags every other day, or "
"tweaking the percentages frequently, consider making it fully dynamic. Try "
"using a dataset that is generated automatically, or computing the content on"
" the fly."
msgstr ""

msgid ""
"Say you have a configuration screen with a list of options and sub-options, "
"and you're trying to find how to better structure this list. Instead of "
"using a feature flag for switching between 3 and 5 options, make it fully "
"dynamic. This way you'll be able to perform other tests that you didn't "
"plan, and get more flexibility out of it."
msgstr ""

msgid "Use the client version to negotiate feature flags"
msgstr ""

msgid ""
"After effectively finishing a feature, the old code that coexisted with the "
"new one will be deleted, and all traces of the transition will vanish from "
"the code base. However if you just remove the feature flags from the API, "
"all of the old versions of clients that relied on that value to show the new"
" feature will go downgrade to the old feature."
msgstr ""

msgid ""
"This means that you should avoid deleting client-facing feature flags, and "
"retire them instead: use the client version to decide when the feature is "
"stable, and return `true` for every client with a version greater or equal "
"to that. This way you can stop thinking about the feature flag, and you "
"don't break or downgrade clients that didn't upgrade past the transition."
msgstr ""

msgid "Beware of many nested feature flags"
msgstr ""

msgid "Nested flags combine exponentially."
msgstr ""

msgid ""
"Pick strategic entry points or transitions eligible for feature flags, and "
"beware of their nesting."
msgstr ""

msgid "Include feature flags in the development workflow"
msgstr ""

msgid ""
"Add feature flags to the list of things to think about during whiteboarding,"
" and deleting/retiring a feature flags at the end of the development."
msgstr ""

msgid "Always rely on a feature flag on the app"
msgstr ""

msgid ""
"Again, there is no such thing \"too small for a feature flag\". Too many "
"feature flags is a good problem to have, not the opposite. Automate the "
"process of creating a feature flag to lower its cost."
msgstr ""

msgid ""
"function processTransaction() {\n"
"  validate();\n"
"  persist();\n"
"  // TODO: add call to notifyListeners()\n"
"}\n"
msgstr ""

msgid ""
"function processTransaction() {\n"
"  validate();\n"
"  persist();\n"
"  if (featureIsEnabled(\"activate-notify-listeners\")) {\n"
"    notifyListeners();\n"
"  }\n"
"}\n"
msgstr ""

msgid ""
"title: \"Feature flags: differences between backend, frontend and mobile\"\n"
"date: 2020-10-19\n"
"updated_at: 2020-11-03\n"
"layout: post\n"
"lang: en\n"
"ref: feature-flags-differences-between-backend-frontend-and-mobile\n"
"eu_categories: presentation"
msgstr ""

#~ msgid ""
#~ "title: \"Feature flags: differences between backend, frontend and mobile\"\n"
#~ "date: 2020-10-19\n"
#~ "updated_at: 2020-11-03\n"
#~ "layout: post\n"
#~ "lang: en\n"
#~ "ref: feature-flags-differences-between-backend-frontend-and-mobile\n"
#~ "category: presentation"
#~ msgstr ""