How to deliver 3x faster with effective API design
This is a modal window.
The media could not be loaded, either because the server or network failed or because the format is not supported.
Formal Metadata
Title |
| |
Title of Series | ||
Number of Parts | 131 | |
Author | ||
License | CC Attribution - NonCommercial - ShareAlike 3.0 Unported: You are free to use, adapt and copy, distribute and transmit the work or content in adapted or unchanged form for any legal and non-commercial purpose as long as the work is attributed to the author in the manner specified by the author or licensor and the work or content is shared also in adapted form only under the conditions of this | |
Identifiers | 10.5446/69455 (DOI) | |
Publisher | ||
Release Date | ||
Language |
Content Metadata
Subject Area | ||
Genre | ||
Abstract |
|
EuroPython 202479 / 131
1
10
12
13
16
19
22
33
48
51
54
56
70
71
84
92
93
95
99
107
111
117
123
00:00
Optical character recognitionReceiver operating characteristicMathematicsBuildingLevel (video gaming)Product (business)Event horizonMultiplication signDomain nameComputer animation
01:12
Musical ensembleComputer animationLecture/Conference
01:39
Design of experimentsClient (computing)Multiplication signTelecommunicationStandard deviationDivisorServer (computing)Thermal expansionEndliche ModelltheorieComputer architectureMathematicsConnectivity (graph theory)Representational state transferDependent and independent variablesDifferent (Kate Ryan album)Operator (mathematics)Set (mathematics)Client (computing)InternetworkingShared memoryLevel (video gaming)Computer animation
03:09
Client (computing)Connectivity (graph theory)Server (computing)MereologyInteractive televisionCartesian coordinate systemDependent and independent variablesHeegaard splittingComputer architectureClient (computing)Endliche ModelltheorieUser interfaceMobile WebMobile appComputer animationLecture/Conference
04:19
Broadcast programmingComputer configurationCharge carrierWhiteboardBeat (acoustics)Product (business)CASE <Informatik>Type theorySoftware testingTouchscreenWeb pageMobile appAndroid (robot)outputClient (computing)Integrated development environmentMultiplication signOverhead (computing)TelecommunicationInteractive televisionImplementationProcess (computing)HypothesisWeb browserFormal languageCodeDifferent (Kate Ryan album)Endliche ModelltheorieServer (computing)Arithmetic meanConsistencyBuildingWeb 2.0FrustrationCrash (computing)Computer animation
06:59
Client (computing)Representational state transferProduct (business)Pattern languageFront and back endsComputer animationProgram flowchart
07:35
ResultantDependent and independent variablesPrototypeProjective planeComputer animation
08:22
Front and back endsLevel (video gaming)SpacetimeClient (computing)DebuggerPresentation of a groupView (database)Dependent and independent variablesLecture/ConferenceComputer animation
08:59
Router (computing)Personal identification numberCloud computingSpeciesMultiplication signView (database)Level (video gaming)LogicSound effectBuildingCycle (graph theory)IterationOrder (biology)Latent heatParameter (computer programming)Front and back endsCodeClassical physicsSpacetimeData Encryption StandardClient (computing)Dependent and independent variablesRepresentational state transferBitDebuggerMobile appWeb browserSoftware developerComplex (psychology)Mathematical optimizationComputer configurationTransformation (genetics)ImplementationPresentation of a groupConnectivity (graph theory)Heegaard splittingLibrary (computing)Mobile WebComputer animation
12:03
Server (computing)Computer configurationPressureBit rateRaster graphicsIntrusion detection systemExecutive information systemQuery languageComputer configurationVolumenvisualisierungClient (computing)View (database)Web pageSingle-precision floating-point formatDependent and independent variablesField (computer science)MappingConnectivity (graph theory)Visualization (computer graphics)Pattern languageStructural loadLattice (order)Element (mathematics)Multiplication signLocal ringObject (grammar)Descriptive statisticsEmailProjective planeCASE <Informatik>Server (computing)Scheduling (computing)Social classImplementationSequenceLibrary (computing)SoftwareTransformation (genetics)MathematicsOcean currentInformationSystem callArtistic renderingLine (geometry)Point (geometry)Mobile appCodeProduct (business)Mobile WebPauli exclusion principleConsistencyCross-platformCodeContext awarenessFront and back endsContent (media)Uniform resource locatorType theoryGreatest elementMessage passingCompilation albumData managementGraph coloringTelecommunicationWeb 2.0InjektivitätAdditionQuicksortComputer animationSource code
18:05
Cross-site scriptingCone penetration testDecision theoryMathematicsMultiplication signClient (computing)Product (business)Pattern languageComputer configurationTelecommunicationView (database)Server (computing)Phase transitionConsistencyData managementComputer animation
19:16
Mixed realityClient (computing)Product (business)Moving averageSubsetTelecommunicationInternet service providerMultiplication signComputer animation
20:09
Event horizonContent (media)CodeEvent horizonBootingComputer animation
20:56
Front and back endsGroup actionMobile appLecture/Conference
21:47
Order (biology)ImplementationMathematicsElement (mathematics)Latent heatWeb pageDifferent (Kate Ryan album)Front and back endsClient (computing)CASE <Informatik>TelecommunicationSoftware developerFile formatDescriptive statisticsBitServer (computing)Multiplication signLecture/ConferenceMeeting/Interview
23:08
Web applicationoutputAndroid (robot)Mobile appServer (computing)Data storage deviceDifferent (Kate Ryan album)Web 2.0Lecture/Conference
23:41
Boss CorporationSoftwarePresentation of a groupCartesian coordinate systemQuicksortBoiling pointOverhead (computing)DatabaseClient (computing)CodeServer (computing)CASE <Informatik>BitGame controllerBoilerplate (text)Fitness functionIdentity managementComputer configurationMobile appGraph (mathematics)Endliche ModelltheorieOrder (biology)Level (video gaming)BuildingConnectivity (graph theory)LogicMultiplication signService (economics)Computer architectureFlow separationArtistic renderingLecture/Conference
26:48
Serial portProxy serverPoint (geometry)DatabaseField (computer science)Dependent and independent variablesMereologySoftware testingFront and back endsCodeDebuggerOverhead (computing)Software frameworkData structureGoodness of fitLecture/Conference
28:04
Front and back endsSpacetimeMultiplication signLogicRight angleDebuggerCodeClient (computing)HTTP cookieLecture/Conference
29:08
HTTP cookieLecture/ConferenceComputer animation
Transcript: English(auto-generated)
00:06
Hello, everyone. I participated in many Europythons before, always as an attendee, and I always had a really great time. So this year, for the first time, I decided to also submit a talk, and I'm very excited
00:22
to have the opportunity to be here today on stage with all of you. I work at kivy.com, the global travel tech company. At kivy.com, we use Python to build innovative product for travelers, and my team specifically
00:41
works with disruptions and travel emergencies domains. Working with travel emergencies can be sometimes quite a challenge. I remember a few events, especially during the COVID pandemic, and also shortly after
01:02
an outbreak of war in Ukraine, when we had literally just a few hours to deploy changes to our production. And we used to struggle a lot with this.
01:37
Sorry for the minor technical issue. We used to struggle a lot with our delivery times.
01:43
Today, in this talk, I will share a few tricks and a few changes we did to our architecture to be more efficient. I bet you've seen a similar picture before. The client server model is with us for a long time.
02:01
It's probably fine to say that since the expansion of the internet, and it cannot work without a good API. Historically, there have been many different approaches we used to render HTMLs from the servers and different things.
02:21
What became, over recent years, the factor standard for client server communication is the concept of REST API. In REST, server typically exposes a set of resources. Our typical REST could look like one resource giving you all the data about bags, another
02:41
one for refunds. And the client uses predefined operations to interact with these resources. A good example might be getting all the baggage-related data for target booking or doing post requests to, let's say, submit refund requests.
03:02
And the responsibility of the client is to use these low-level resources and transform them into UI components that are communicated to clients.
03:25
Client server model with REST is simple and flexible, and in the traditional client server model with a three-tier architecture, we have a clear split of responsibilities where server is responsible for the data layer, encapsulating the data plus the application
03:46
layer, while on the client, we have the user interface and user interaction. Over a decade ago, the age of mobile began, and mobile devices slowly started to dominate
04:03
the landscape. When we take a look at our data as an example, in the post-booking part of KiwiCom app experience, over 80% of users prefer use the app on mobile device.
04:21
So what does this mean to our client server model? We still have one server, but now it needs to serve three different clients, typically the iOS and Android native apps and the web client. What makes this challenging is that each client has different requirements.
04:43
On the technical side, the good example might be that the mobile device prefer to make only one request per page that is rendered, and on the UI and product side, the most visible thing, the screen size, is smaller for mobile device, and also we
05:04
have different types of interactions like push notifications, live activities, and so on and so on. The second issue we have, and this most probably depends on the size and team layout of your company, but in our case, building smaller or average feature means that we now
05:26
need to involve three engineering teams, and you can probably imagine that this introduces significant communication overhead. And finally, whatever code lies on the client side now needs to be implemented three
05:42
times in three different languages. We need to test it all, and especially in the product-oriented environment, this is a significant issue. I'm not mentioning those travel emergencies. We always like to iterate quickly. We want to set up an A-B test in a few weeks, collect the data, see if it works,
06:03
and then either promote it or move on to another hypothesis we want to test. So all of these processes, triple implementation, communication overhead, is slowing us down. And this triple implementation can also lead to inconsistencies on the clients.
06:26
Let's check this example. On the Android app, native app, we had this banner colored differently. We figured it out short before the planned release. If there is some minor edge case not covered, one of your clients can just start crashing.
06:46
And I remember also this one. On the iOS, it started after some release just rendering a blank page completely silently. It wasn't even visible in our monitoring dashboard. Quite frustrating.
07:00
Let's now take a look at the schematic overview of the general purpose REST API and three client setup. It's quite messy and complicated, isn't it? So what can we do to improve this? When we started our research, the pattern called back-and-forth, front-end, took our
07:21
attention. Who knows? Back-and-forth, front-end. Can you raise your hands maybe? Quite a few. Who uses it on production? Something similar? Just kidding, people. Okay. With our engineering team, we don't like lengthy waterfall projects, and what we like
07:43
to do is more like reuse existing solutions, build quick prototype, deploy it, and see the result. Sometimes we realize it works well. We realize that some specific aspect needs further improvements, or we can see that it's
08:00
turned out not to be a good idea at all in the end, and we need to find different solution. And also, when adopting BFF, we took similar approach, and those REST APIs, they are okay. Then they can stay there. And their responsibility is simply to still encapsulate the data and expose those low-level
08:24
resources. Then we introduced this new back-and-forth, front-end layer and connected it to the REST endpoints, and its responsibility is to take those low-level resources and transfer
08:47
them into higher-level views. And we technically migrated a significant portion of the presentation layer from the clients here into this shared space.
09:00
And finally, for those new BFF-style endpoints, we reworked our clients a bit. They are now much thinner, and we connected them into this BFF layer, and their responsibility is now simply to display stuff, to take the prepared view and render the components.
09:21
With this setup, we efficiently mitigated the triple implementation. It is still there, but much, much smaller piece of logic. But over time, a small API parameter called client ID appeared in our request to BFF, telling the handler that I am mobile client or I am the web client.
09:45
And we realized that the problem of specific requirements is still there, and it's significant. In order to deal with this one, we, in our second iteration, split the shared BFF
10:01
into two pieces, one BFF specifically tailored for the needs of native mobile apps, and a separate one for the client. And now we have the flexibility that we can adjust the release cycle, API versioning, and everything, and also build endpoints, specifically targeting needs of each client.
10:22
While if it makes sense, we still can share some code or even the whole views between those two in a shared library. And as we, of course, implemented our BFF in Python, a very nice side effect is that
10:40
we now have more Python in our stack. And also, this BFF became some nice shared space where both front-end and back-end engineers can collaborate. As is a presentation layer built in Python, it's mostly about some API calls and transformation of the data onboarding front-end engineers here wasn't an issue.
11:07
Let's now try to summarize the main advantages of BFF adoption. First is definitely the customization. The now we have option to build really customized endpoints for specific needs of
11:23
each client, satisfying the requirements. It can also bring some performance optimizations, as now we typically make only one request from the client to BFF layer. We can easily prevent over-fetching of the data.
11:42
And also, the complexity of client development is significantly reduced. I mentioned the higher level of views served from BFF a few times, and this means we need a new style of API for this, as these are not the classic REST API resources.
12:05
Here in this case, we opted for another pattern, which is called server-driven UI. Again, the same exercise. Anybody in the room knows it? Not that many people. Okay, so let's take a look at server-driven UI.
12:23
The main idea is that we now represent the concrete visual components through JSON data. As you can see in this example, there is a one-to-one mapping between the JSON fields in the response and the concrete visual components we render on the client.
12:44
For each component or element of the UI, like in this example, the header title and description, we have a dedicated JSON field containing already translated localized text that is ready to be displayed. If, let's say, we work with some daytime objects, we will convert them to the local
13:05
daytimes to ensure that everything in the response is ready to be displayed. In case of clickable elements like this one, alongside the translated text, we also provide the predirection URL in the response.
13:25
As for this banner in the bottom, we even specify the type of the component. In this case, it's type warning. On the client side, this is passed into the shared UI component library, the library
13:40
of shared tested components that are reusable, and it defines the message and the color of the banner. In this case, the orange color. And let's now imagine that our product manager wants us to change it to have a stronger message and communication with a single line change in the BFF layer.
14:02
We will change the type from warning to, let's say, critical, and the color of the banners across all the clients listening to this endpoint will change immediately and consistently right away after the backend release. So a single line change defines how the UI should look like.
14:25
As for the main benefits of server-driven UI, this is what can ultimately make your production releases faster. As for those specifically for those smaller or like mid-sized features, you typically don't need to touch clients at all.
14:41
That means no coding in Kotlin needed or Swift, no need to release and wait for the App Store approval, no need to push your users to update the app. Just release and immediately propagate it to all the clients.
15:02
As we control it from one place, from the backend, we can also ensure cross-platform consistency as long as they listen to the same endpoint or the endpoint response is correct. We need to be, of course, careful if we have two BFFs still about the web versus
15:21
mobile consistency. And also, if we are building some really personalized content and pages, rendering this or preparing the view on the backend has the benefit that we have all the context and all the data at hand. Let's now take a brief look on our concrete implementation of BFF and server-driven UI
15:46
in Python. This is a very simple view class which is responsible for rendering a single page of the UI. Check it out.
16:03
As we, for the beginning, built this BFF layer on top of a single Python project, we considered it unnecessary to introduce additional network calls. What we did instead is that we've wrapped existing Flask handlers into this MMB client
16:21
library and we just do method calls to the REST API handlers directly from Python code. Here in the render method on the top, you can see a sequence of these REST resource calls. In this case, we need generic info about the booking and then some details about the current
16:45
schedule change offer for the booking. So we do this sequence of resources, we fetch the REST responses, and then we do all the transformation, localization, and we compose the server-driven UI style response
17:02
that is returned sort of to the clients. As a single UI page is typically centered around one entity or a couple of entities, in our case it's typically one booking, if you have some more complex view and there are really like too many render, in the render method, too many REST calls, it can
17:25
happen that on the background there will be just too many very similar or repetitive SQL queries, as it's all around one ID, one booking, and you call many, many REST handlers. If this becomes an issue, we have an option to pre-specify a couple of entities we want
17:46
to preload, and this will, on the background, be represented as SQL alchemy query using the join load technique to preload all those entities and cache them for the whole time
18:02
of the rendering of this view. Adopting these two patterns, we became more efficient and we improved our production delivery time. Thanks to BFF, the client-server communication is now simplified, and we also have an option
18:23
to build those really like customized endpoints when needed. The server-driven UI pattern helped us to be much more efficient and have a faster production delivery, alongside other benefits like the personalization and consistency across
18:45
all the clients. What also proved efficient here, and also a few times before, is to not do waterfalls, but instead slice the end goal into small, manageable pieces, and then in each phase
19:01
deliver something, start, let's say, with one or two endpoints, build in the new style, and then evaluate what works, what needs some changes, and based on that, make an informed decision on the next steps. So if some travel emergency occurs today, we can just ask our content writers to provide
19:24
new communication, new text. We can, in the personalized way, pick the subset of bookings that are affected, and in the BFF, we'll simply update the text of the banners. We can easily change the styling to more strong, stronger styling, or even introduce
19:43
new banners in no time and roll them out to production easily the same day. And this slowly concludes the talk, but definitely not the story of three clients. So we definitely need to continue exploring both the architectural and the technical side
20:02
of our solution to make sure that with each step and iteration, we become more efficient. I would like to thank you to my amazing colleagues from kibi.com for the support when preparing this talk, and if you are interested in more tech content or events,
20:23
I would like to invite you to follow our tech community called kibi.com. If you have any kind of questions, I will be happy to answer them either right now or also feel free to stop by later for some private chat at our kibi.com booth later
20:45
or reach out to me on my LinkedIn. Thank you. Thank you, Michael, for this wonderful talk. So we're now entering, as you might expect, the Q&A session.
21:02
So feel free to come to the microphone and ask for questions regarding this talk. If not, you can also write it down on Discord or watch it. I have not seen any questions on Discord so far. And we've got the first person on the microphone, so please speak. With the backend rhythm UI, do you just send the banners or you send the complete UI
21:24
similar to nice? You are a nice guy. So you just have an app that renders these JSONs or the mobile apps have still a lot of built-in actions and they are dialogues, or can you all define that in the backend?
21:45
I would say there is no straightforward answer to this. Each page is different. Some is really simple, like the title, description, and banners. Some is more complicated. So I would say it depends on the specific use case. But in general, we try to have as much as possible defined from the backend.
22:05
Sometimes it's more or less. But there is still, of course, something on the client, the formatting, the ordering of the elements sometimes. But the idea is that if we want to introduce new reusable component or change the text, change the formatting,
22:22
that should be possible from the backend only. I think also with the server-driven UI, there are many companies using it and each concrete implementation is a little bit different. Somebody is going as far as defining even maybe the centering of the elements. In our case, it's mostly defining the title, description, banner with the data,
22:43
sometimes the order of the elements with the data, but it really depends. And of course, if it's more complicated, completely new feature, the mobile development is needed. But at least for, I don't know, 80% of use cases, when we are changing the communication or introducing new banner, we should be now capable of making it without touching the clients most of the time.
23:06
Cool. So another question, other side. Let's switch and parallelize. First, thanks for the talk. I haven't heard about server-driven UI. My question is kind of follow-up from the previous one. Why don't you just do a web app? You don't need an app store anymore.
23:24
You don't need different apps for Android and iOS. You can deliver even faster. So what distinguishes your server-driven UI from just having a web app? I think we cannot say that there is one size fits all solution.
23:43
There are several approaches, again, like somebody is using HTMLX. Somebody can be maybe rendering HTML directly from server. And as I said, we are moving step by step, exploring. We did some experimentation with GraphQL. We figured out it's not use case for us.
24:02
Then we did this step from heavy client to thin client and server-driven UI. This specific solution, I don't know. It's an option. Maybe some other team in Kiwi tried it out. So I cannot provide a clear answer that it is or it is not a fit for our use case. But definitely, we can see that we are kind of circling back
24:23
towards the heavy server-controlled UIs, maybe a little bit going back to the age when we were really sending HTML. And it has significant benefits to do it. Okay. So we got on the other side another question. Yeah, with the BFF layer, is it possible for the APIs, the REST APIs,
24:44
to return JSON directly and then just cut out the BFF layer and have the logic in the REST component? You mean more like building server-driven UI style directly on top of the database without the BFF layer or something like that? Yeah.
25:01
I think this approach would solve most of the problems. And as I explained, the BFF is basically just on the code level, just another package enforcing some isolations. We basically wanted to have it in order to have the isolated layers,
25:20
because there are also many contributors to do some really nasty stuff like taking SQL model and directly building, I don't know, whatever presentation layer on top of it. So it's mostly for the isolation there. And I think if maybe the architecture is not that complex or there are not that many services, building server-driven UI directly on top of the database models
25:44
would also work quite nice. There is also maybe sometimes some overhead of the extra layer, extra boilerplate code. So this could work in our case, mostly having it nicely defined, isolated, to sort of have maybe those layers like this is the application layer,
26:04
data layer, and the presentation layer. But I think it's not that important or significant if it's really there as an extra layer connected through network or it's not there at all. Or it could be maybe some identical models
26:21
like connecting the application layer models to the UI rendering. There are, I think, many solutions. But for a simple app, maybe today I would go for the SQL Academy models or Fuzz API, identical models, and probably server-driven UI layer maybe directly on top of it.
26:42
We've got time for another switch to this side. Okay, thank you for the talk. So what are, according to you, the disadvantages of BFF and what are the most challenges? Maybe that overhead, that if one endpoint or the response is really simple, just like a few fields,
27:03
with BFF, you need to go through all the layers. You need to edit as a field to the database. Then you need to create the rest endpoint as a proxy, and the BFF is another proxy. So sometimes it depends on the framework you use, but there can be some overhead that are too many layers, serialization, testing.
27:22
So this, I would say, is the most significant disadvantage. Good. Now a last quick question. Two minutes left. So I was wondering if this backend-driven UI approach doesn't complicate a lot of things on the backend.
27:41
I mean, normally there are things like some kind of labels which you only have to worry about on the frontend, and with the backend-driven UI, you probably have to also store them on the backend somewhere in the code, and doesn't it complicate the structure of the code quite a lot?
28:01
Not sure if I really understand the part with the backends, you said? Yes, I mean that some labels, which you normally would store on the frontend and just use them to display data from the API, with this approach you'd have to store them on the backend, right,
28:21
in the backend code base. Doesn't it somehow complicate managing this code base? Maybe I'm wrong. Of course the logic needs to lie somewhere, so we sort of moved it from the client to the backend, and there is a little more work, but I don't know.
28:41
At least it's now in Python. There are more people who know how to build it. I think in general, at least it's not three times, it's once in the shared space, and this setup seems to be more efficient, faster delivery, and we did encounter some huge issues, like this is easy on backend and on frontend,
29:01
and in BFF layer it would be complicated. Great. So thank you also from my side. Again, applause, and nobody goes away without cookies. Thank you.