Skip to main content

Building Better Apps: Architecture Best Practices and Common Patterns on Databricks Apps

Summary

  • Databricks Apps fall into three categories—agentic, analytics, and transactional—and this video presents four cross-cutting architectural principles that apply equally to all three: connectivity and state, identity and authorization, agents and async, and performance.
  • The connectivity principle centers on choosing between Lakebase for low-latency OLTP reads and writes versus Databricks SQL warehouses for OLAP queries, and mixing both within a single application when different parts of the data flow require different latency profiles.
  • The performance principle covers triage, caching strategies, and using Lakebase for sub-millisecond reference data reads that keep the UI snappy, as well as streaming agent responses asynchronously to prevent blocking the user interface during long-running LLM calls.

Building Better Apps: Architecture Best Practices and Common Patterns on Databricks Apps

Watch: Building Better Apps: Architecture Best Practices and Common Patterns on Databricks Apps
Building a data-driven application is easy; building one that is secure, performant, and scalable is where most teams struggle. this video provides a definitive field guide to the architectural patterns used by the most successful builders on the Databricks App platform. We will break down the ""how-to"" for the most in-demand app categories: Internal Tools, AI Copilots, Agentic Workflows, and Customer-Facing Products. For each pattern, we will dive into the technical specifics that matter most: Connectivity & State: Best practices for integrating with Databricks SQL and Lakebase. Identity & Auth: Implementing On-Behalf-Of (OBO) tokens and service principal delegation to ensure data privacy. Agentic Design: Orchestrating LLMs and tool-calling within a full-stack environment. Performance: Strategies for caching and low-latency UI responses. Join us to learn how to avoid common pitfalls and leverage standardized blueprints to ship better apps.
Talk By: Anant Pingle, Sr. Specialist Solutions Engineer, Databricks ; Naïm Achahboun, Forward Deployed Engineer, Databricks ;

Chapters

FAQs

What are the three categories of Databricks Apps?

The three categories are agentic applications (multi-agent systems where LLMs and tools are orchestrated to produce outcomes like answering questions or creating orders), analytics applications (custom data visualizations beyond what AI/BI Dashboards provide natively), and transactional applications (apps with create, read, update, and delete workflows backed by operational data).

When should a Databricks App use Lakebase versus a SQL warehouse?

Lakebase is a Databricks-managed PostgreSQL service optimized for low-latency OLTP reads and writes, making it the right choice for transactional workflows, user preference storage, and high-frequency reference data lookups that need sub-millisecond response times. SQL warehouses are better suited for OLAP queries over large datasets, and many apps use both in the same application.

How does the two-lane authorization model work in Databricks Apps?

The two-lane model separates app-level authorization—where a service principal acts for all backend calls—from user-level authorization via On-Behalf-Of (OBO) tokens that scope downstream access to the individual user's permissions. The Connections API provides reusable credential management so these identities do not need to be hardcoded or managed per-deployment.

How should Databricks Apps handle agentic and asynchronous workflows?

Agentic workflows in Databricks Apps should stream agent responses to the UI rather than blocking on a synchronous reply, preventing the application from appearing unresponsive during long-running LLM calls. The architecture should also include resilience patterns such as retry logic and fallback behaviors to handle the probabilistic and occasionally slow nature of LLM tool calls in production.

Full transcript

[00:08] Thanks Alson. Thanks guys for joining us today both in person and online. As said we'll be presenting on data bricks apps in particular how you can build good apps that are fast, performant and safe. Uh before we did that we were introduced. So these are our pictures.
[00:22] You can find us on LinkedIn if you want to connect. Always happy to skip this slide. Um, first off, I want to quickly introduce the topics we're going to talk about by looking at
[00:34] several different types of applications that can be built. We'll then have four, let's say, principles that we want to deep dive into that are, let's say, at the foundation of every single application. First one is connectivity
[00:46] and state and identity and O. It's going to be covered by Anant and I will take anything regarding agents, asynchronous communication or programming and performance. Uh, we will not probably be able to take questions. So please if you
[00:59] have them uh connect with us offline and we'll try to answer those as well. regarding the the first piece of our presentation, right? Why why are we looking at these principles? Um it's
[01:12] because there is like plethora there's there's many different types of applications and if you try and like say optimize for each type of application individually, it's not an exercise that you can sustain, right?
[01:24] You can say like okay, for an ERP system I need to do these and these and these things and for a CRM I need to do XYZ. Like it's an it's an infinite exercise which really doesn't end. So the core
[01:36] focus of this presentation is looking at all of the different types of apps across all sorts of categories. What are the things we can distill and particularly on data bricks apps that if you do those things right any app or
[01:48] agent or application is going to have a solid foundation. Now we've got three categories here that we see a lot primarily when we look at the work our customers are doing. A big
[02:01] category like really growing fast is the agentic applications. Think of this as a container or let's say a multi- aent system where you have different NLMs and different tools being called within the
[02:13] app container and producing an outcome for the user right so think of like creating an order or answering a question producing a chart um the second type is I would say more traditional right the analytic application
[02:26] in data bricks we have a native right BI product AIBI dashboards it's very powerful now you have lots of visualization types but sometimes times customers really want to go fully custom, right? They want to have a 3D map of the globe and like fancy
[02:39] animations, then AIBI dashboards can help you. In which case, data works apps is a is a good contender to create those types of use cases. And the third one I would say is is more on the transactional processing side where it's
[02:52] like the typical list or form where you're collecting entries. Usually these are backed by lakebase. uh when it comes to data bricks apps essentially it's you're updating a list creating new entries deleting them um
[03:07] I think the main point here across all these categories is that the the architecture principles remain the same and we'll take over from there >> yeah thanks thanks na so um I think by
[03:20] the way before we start who here has uh already built an app on data bricks before okay it's a good Awesome. And uh who here just builds apps uh without any
[03:33] coding agents nowadays or do you use some kind of coding agents? Show of hands who do. Cool. So yeah, so there are some core principles that we
[03:46] recommend to customers that u help you essentially create um the best so apps on data bricks with the best uh principles and these principles are listed here and we're going to go one by
[03:59] one into each of them and then also show you um how they work and so on. So uh but before that why why do these architectural principle matter right so
[04:11] we are currently in like this era of uh egentic wipe coding applications so I think we all use different kinds of coding agents may be claw or giode or um codeex whatever you say and um for a lot
[04:27] of us when we are doing these kinds of applications with these coding agents the um let's say the goal turns turns out to be first that it needs to work and in and it needs to get all the functionality and um what these coding
[04:41] agents also tend to do is essentially make it work right like whatever possible and what you need to do essentially as a user is like nudge the AI into the right direction to follow
[04:53] some architectural principles and these architectural principles are what makes a good app compared to just a demo that just works you know like a small prototype So let's uh discuss the the
[05:07] the the the four architectural principles one by one and then let's uh look at how they look like in in practice.
[05:19] So the first one is uh connectivity and state. So you might be aware that in data bricks when it comes to compute we have different kinds of engines. We have lakebased which is our Postgress offering uh um in within data bricks and
[05:33] we have have the lakehouse so that's more for your OLAP queries and so on. So when it comes to um when you're vip coding an app, it could very well be that
[05:46] task, right? So uh the typical use cases that you see with lakebas are more when you have to have like low latency reads like you have a lot of concurrent users, you have fast writes, fast reads, uh you
[06:00] want like the UI to be really snappy. So things like updating the application state or for example populating a drop-down. So these are like the kinds of use cases where you need an old TP
[06:12] database. But that's not only like like especially now we're building all these data and AI applications. So um these kinds of use cases are not the only ones that power the applications right we
[06:24] also have a lot of OLAP use cases. So we have huge amounts of data uh sitting in the lake um and we have to basically do some uh analytics on top of it. to do some aggregations have large amounts of
[06:37] records that we have to scan aggregate them um and and and so on and for that we essentially have DBSQL or lakehouse and that's what
[06:50] cases right so you have OLTP OLAP and it's important to know I mean I think we all know the difference between the two but it's essentially good to know where to use what and how to uh use them it's
[07:03] also of course not like only either or you can also use a combination of both and I'll touch upon that very quickly as well but essentially idea is that you have two engines meant for separate things so know what kind of use case is
[07:17] meant for what engine so um I have some examples here so for example let's say you want to do these point lookups so you have um you
[07:29] essentially need to really fast get some kind of values from your database So this is like a typical use case where you would need an OOLTP database. So that's where lakebase is a good fit. Uh when you're doing things like updating
[07:42] your application state, storing user sessions, you want this to be really snappy as well. It should be able to hand handle a lot of concurrent rights at the same time very fast. And you also use lakebased or something like that. But let's say you have now these
[07:55] dashboards or you have some kind of uh reports that you have in your application or visualizations that you have to show and for those you would typically use something like DBSQL because it's you know it's columnar it's
[08:08] meant for aggregation queries for joins with large tables and so on. So yeah uh pick the engine by the right query shape right? So uh just to demo this I'm going
[08:20] to switch my screen a little bit. So I think who here has uh taken a flight to to get here? I think a lot of us and a lot of us have also come from different
[08:32] countries. So we thought the best example would be to show like a live flight tracker. So what we have tried to do is uh create like a sort of air traffic control kind of application here where you see like live planes at this
[08:45] point in time flying above us. Uh I've tried to go a bit more in the Bay Area but um by the way this was also this is built end to end on data bricks. So you have spark structure streaming real-time
[08:58] mode processing the flight records. It's doing all this alerting logic raising these alerts evaluating fences geo fences and so on. And then we use lakebased to store the data but we also have analytics. So we use DBSQL and then
[09:11] we essentially use a data bricks app to serve this. So um this app is built end to end uh with data bricks and I think it's a cool example to show um the the topics that we're talking about. So now
[09:25] in my air traffic application I have an analytics tab because I don't want to just look at what's going on live but I also want to do an historical analysis. So let's say um I want something like this right. So I have a table where I
[09:38] have history about all the flights in the past and I want to do like an analysis at what point in day uh like a heat map to see like at what point where there was the highest density of planes.
[09:50] So you can see I think it's common everywhere that during the night you have less flights but then during the day it keeps growing and so on. So these are sort of like typical analytics OLAP kind of queries and um what I want to
[10:05] show you is that I'm going to run like I've loaded both the tables in lake base and in the lakehouse. So uh and we're going to try to query both of them to for you to see that hey picking the
[10:18] right engine matters right. So now I'm going to do like a table. I have a table with all my live positions. I want to do a point lookup. I want to see like for this flight number um what is like um
[10:30] yeah what is the latest uh signal that I received. So if I run the query um on both the engines. So you can see I ran one on lake base. I ran one on DBSQL and
[10:44] you can essentially clearly see that um um lakebase is the right fit. It's like if I also run it again you can see point lookups really fast snappy and you would use lakebase for something like that.
[10:57] DBSQL has has caching. Of course, you can see um that this result was probably taken from the cache, but you can still see uh the difference between using an OLAP uh kind of um yeah warehouse for
[11:11] this versus using like a Postgress OLTP kind of system. Similarly, let's go over like um an aggregation query, right? So I want to see this chart that's populated
[11:23] here that I have on my flights data and I want to see that hey which country had the most like registrations for the flight. So I would run this exact same query now on the lakehouse and I would run this on lake base and you can see
[11:37] that DBSQL is is really fast here. So my SQL warehouse is essentially has this result computed but the lake base is is still running because that's of course
[11:49] not the right fit or not the right engine for this. Um I know that this takes around like 50 seconds to execute. So I'm just going to move on. But uh yeah another example I I
[12:03] have here is like I want to see like the last 20 positions for a particular flight and I do the same. You can see that lake base is really fast here for doing these kinds of lookups. Whereas with DBSQL, you see uh some some kind of
[12:18] uh higher latencies here. Uh you would wonder like hey what if I have something like I have a mix of an OLAP query together with OLTP. So I have like some updates coming into my old TP database
[12:31] and I want to also join it essentially with like my huge table and I want to do some analytics with that data. So you can you can use by the way this is uh already possible today with DBSQL. So in
[12:44] the DBSQL you can have lakebased as a as a catalog and you can reference the lakebased tables directly and you can join the OLAP and OOLTP tables together and get your output. But with what Ali
[12:56] announced this morning with Raiden, this is going to be even faster. So you will see really good latencies when you use uh the lakehouse uh in the near future.
[13:14] So going back to my presentation. So what I really wanted to highlight with um this one um yeah I just showed you the demo but what I really wanted to highlight is pick the engine by the query shape and not with what's
[13:26] familiar. And when using coding agents it it tends to happen really that um you tend to use the wrong kind of engine for the wrong kind of use case. So good to keep that in mind.
[13:40] Let's talk about identity right. So um what typically happens is now you have this data application you have unity catalog you have all your data in unity catalog and what you want is like when a
[13:53] user accesses the application the when you access the data you would want that because in unity catalog you have all your access controls you have your rowle security column level mass and what you would want is that when I anant is
[14:08] accessing the application it needs to be that my permissions are respected and um and and I I see the data based on like what rights I have rather than using like a shared um shared kind of service
[14:21] principle, right? Because there are problems uh when it comes to using a shared identity when you're prototyping, it's usually fine. So if you're using your coding agents, you're going to see that hey, it's going to just use a service principle. So by the way, when
[14:34] you uh deploy a data bricks app, there is a service principle created with it. And if you essentially um don't take care of it, that's the identity that's used for running all the queries. So
[14:46] during prototype that's fine because the goal of what I'm doing during prototyping is to see if it can work or not. But when you want to do it on a in production or enterprise scale, the the question really changes to who acted
[14:59] with whose authority and can we prove it, right? And when you use a shared identity, you cannot answer questions like hey which user read this PII data which app triggered this alert or okay the user has left like is there an audit
[15:11] trail of what what happened and so on. So these are the questions that you get answer to from unity catalog but it's essentially that you use the right identity to access this data
[15:23] with data bricks we have two lanes of authorization. So like I mentioned by default what happens is that the service principle that's used or that's created with the app is what um essentially is
[15:35] used to run all your queries. So the way that happens is that uh there is the client ID and client secret of the of the service principle that's injected into your app's compute and that's
[15:48] what's used when you run your queries. uh but what we have um and this is the best practice that we recommend to customers is that when you're talking to data where you need to have the identity
[16:00] proof then you essentially use on behalf of authorization and that's what we offer uh native lane in data bricks as well. So what essentially happens is when I'm querying uh to an application
[16:12] um so by the way this needs to be turned on but um when I'm querying an application uh what happens is that the data bricks proxy injects like uh an
[16:24] access token for the user that's interacting with the application. So this is something that can be extracted from the header and then you can use this essentially to you know initialize your workspace client and call the uh
[16:36] call the right queries with the identity of the user that's accessing the application. Uh so if the question is should I be using app authorization uh with the
[16:48] service principle or should I be using obo the answer is that hey you don't need to use like one or the other but you can also combine both. So for example things where you don't care
[17:00] really about like the identity of who's uh doing it. So for example updating the state of the application in your database or for example scheduling like a maintenance or a background job you can use an apps SP. But when it comes to
[17:14] for example um accessing data which is specific to the user so respecting all the UC permissions or for example when the user is talking to Genie uh you want all the users rights to be respected so
[17:27] you uh you can use OBO over there but you can also combine both of them. So in the same application you can have both. So you have OBO for doing these shared state kind of things like scheduling the
[17:39] background jobs or um um or updating the state and so on. And you can use uh the you can use OBO in order to access uh the data with the user's um identity.
[18:06] that I'm going to run with the shared service principle and I'm going to run with OBO as well. So what I've done for the demo is that uh for myself I've give I've become or given myself more
[18:19] permissive rights on the table so I'm able to see all the data but the service principle is limited. In a lot of cases we see customers not giving access at all. uh to the service principle. So you would see like an error saying hey the
[18:32] SP doesn't have access. But in this case I've uh done it just for the demo. And when I run this you can see that uh the current user is the is the
[18:44] service principle. I can also see that in my query history. So I see that we're using the service principles identity to run this query. And when I switch to OBO
[18:57] uh so I use this forwarded access token then you can see that I see different data. So I go to my query history and you can see that this query was run uh with my identity.
[19:20] So coming back the takeaway I would like uh you all to have from this one is essentially OBO is the default for any application where users see different data right so you have UC permissions they need to be respected obo is the way to go uh for those kind of use cases
[19:36] I will give it to Naim now to discuss two other topics >> thanks um so suppose Now that we've got our connectivity and state set up properly, you know, we've got OBO set up as instructed us to. Um, I want to deep
[19:49] dive into a few yeah, let's say points regarding setting up or building an agent on top of data bricks apps. Uh, first one will be calling any type of foundation model and tool. Uh, second one will be writing synchronous code
[20:02] versus asynchronous code. Why should we care about that? What's the difference? Uh, third one is I will touch on obo again because it's quite important for agents. And the fourth one will be on the MLflow agent server. So I'll touch on all these
[20:15] and show a very small demo to showcase how it's done. The first point with regards to calling LMS or calling any type of tool from the app. Uh I think the the most important thing here is that you realize that
[20:28] database is a platform provides a a large variety of different foundation models out of the box and it's very easy to link those models up to the application. uh you can essentially attach the model serving endpoint either
[20:40] using the UI or using Terraform or an asset bundle and it will be automatically attached. Um if you for whatever reason want to use a model that's not provided by data bricks, I would still recommend you hook it up
[20:52] through the AI gateway that was introduced by Ali this morning because that allows you to still get the proper guard rails and observability. Um I think with tools uh the other direction is mostly with regards to how you would
[21:04] for example use Unity catalog connections. Thank you. Thanks. Okay. So, taking the mic because I think it might be more clear. Yeah. Awesome. So, with regards
[21:16] to how you would call tools and you can think of this as APIs or any other type of software, um, Unity catalog has a connection that you can register and you can attach this connection to an app which can host an agent. The primary
[21:29] benefit here would be if you have a lot of agents or apps built, you can reuse the connection object. So, it's not that each app has to mint its own credentials and you have the same credential minting logic everywhere, but rather you're
[21:42] reusing it effectively across all of the different apps or agents you're building. Um, that's the key thing I wanted to touch upon in this slide. Uh, second point is is more important, I would argue, right? Suppose you you've built your agent or application and
[21:55] you're getting a lot of traction. So, you have a lot of users making requests. Now the way you can do this and let's assume we're talking Python is you can either write the code in a synchronous manner or in an asynchronous manner
[22:08] where the main thing to take into account is suppose we're we're tracing this request as soon as someone comes in and asks a question to the agent um are we going to wait for the agent to respond or are we going to free up the
[22:21] core to start working on other activities that's the key distinction between the synchronous and asynchronous paradigm now for most IO bound applications. Using this like await and async in front of the function is going
[22:34] to give you more performance because usually what happens is you have several users making a query. All of these queries go to the endpoint and the endpoint is yeah it needs some time, right? Usually for most large models it needs a couple of seconds at least. If
[22:48] you were to write it in a blocking way, you would basically prevent that worker or core from doing anything except once the first agent has responded. Um, so yeah, this is a a tip I would say take
[23:00] it into account. So when you when you check the code produced by your your friendly LLM, make sure it's writing it asynchronously so you benefit from the increased performance. Third point is mostly with regards to
[23:13] how you properly govern the agent or make sure it doesn't um let's say move beyond the permission boundary that you want you want it to have. It's just to realize that OBO also applies to any agent you build on data bricks apps,
[23:26] right? the forwarded header can be exposed and can be utilized on any downstream tool calls or any downstream calls to a foundation model or genie. Um, and we think this is this is quite critical, right? Because you don't want
[23:38] your agent to assume a broader permission set than you have in case it starts doing actions you don't like. Um that's why is very powerful and I would definitely recommend it for I would say majority of settings except if you're
[23:51] very certain about the exact permissions you've scoped to the principle because that's the other identity the agent can assume. Now the fourth way is with regards to how do you actually build the agent
[24:03] right from a practical angle um databicks has a very nice package you could call it. It's the MLflow agent server. It's part of MLflow. uh it comes out of the box with let's say some very nice tools that allow you to build an
[24:15] agent easily on data bricks apps. It takes care of a lot of boilerplate. Essentially, you could you could try and write it yourself using fast API, but this would will skip you a lot of headache. Let's call it like that. Um
[24:27] main things are for example giving you streaming responses, right? Where instead of waiting for the foundation model to to return everything, we stream its response back immediately to the browser and you get this nice effect
[24:39] where you see the text appearing in in real time. Um so I would definitely yeah encourage you to check it out if you have the time. Now the quick demo I want to show um is a
[24:51] very easy demo and I've built a very basic flight analyst which essentially shows shows you two things how you can easily call genie from the data bricks app and how we can also call a generic
[25:04] foundation model. Um so I'll just ask a question here to genie um and genie is going to start basically writing you could ask the same question from the genie space. Uh the main reason you would like to probably do it in the app
[25:17] is if you want to give it like a very much custom UI uh or you want to give a custom visualization type to Genie that's not supported by the space. The question I asked is like what's the busiest hour? I think it's 7 o'clock.
[25:29] Yeah. So 7 o'clock bad time to fly. Um now I think the the main other point that you can get from building or integrating with Genie in an app is that you're in full control of any other agents that you call. Um, so it's not
[25:42] just Genie that you have to talk to, but you can have a yeah multi- agent call where, for example, I can ask a question to the LLM. Um, let's say what
[25:54] can you tell me? Yeah, typing is hard with one hand about airplanes. I never tested this before, so it's like a real live demo. No, I think the main
[26:06] point is clear. Uh, we can simply talk to different agents and combine their responses. Um there's a very nice other tool you can probably look into which is AppKit and I think yeah it it told us about the data we've given it which is
[26:19] interesting. Um but getting back to my story the appkit is a uh React framework that's built by data bricks engineering. It's part of our apps team and it has pre-built UI components to interact with for example Genie. It also has a
[26:32] pre-built agent component. So suppose you're not really into like building a very advanced agent. You think it's quite complex, you can reuse the existing React component. Um you basically have to do some config or
[26:44] setup and then it's there out of the box. So I would say um as a starting point, it's a great way to start and you can grow into more complex use cases later on.
[27:01] No, I think the the my main takeaway from from these slides would be that when you look at an agent, I would say look at it as a single component of the broader application. A lot of times what you see is that people try and put a lot of things into the agent where sometimes
[27:14] a a reax would also suffice. Um if you have that let's say hybrid mindset, you tend to have more resilient applications, more resilient or let's say smarter agents. um similar to how we're now like introducing an ontology
[27:27] approach into Genie, you could you could have similar approaches built into your own app uh to increase resilience. Now with regards to resilience, uh very nice characteristic often that a lot of customers like to discuss is how do we
[27:39] make the app more performant, right? How do we make it snappy? How do we make it fast? Um I think I got a few pointers to to talk about. Um first one being okay, how do we actually scale the app compute itself? So when we have got an
[27:53] increasing amount of users, how do we handle that load appropriately? Um second point is okay um when I have an issue what do I need to look at? Do I just blindly increase the compute or do I have like a structured process? Uh
[28:05] other points are mainly just some examples I want to discuss. Now first with regards to the scaling options that data bricks apps provides today. Um the the most basic or easiest
[28:18] one is vertical sailing, right? That essentially means we simply give more RAM and we give more cores to the app instance. Currently there's two flavors. In the future they will be more um this this is this is the easiest way you
[28:31] would argue but the main thing to be aware of is that your app should actually be utilizing the cores. Right? If you have for example a fast API application and you have a single worker even if you give it eight cores it will
[28:43] only use one. So you need to make sure your configuration of the app itself is set up in a way where you're utilizing let's say everything that the vertical instance or the vertically scaled instance is giving you. Now the other way of scaling is horizontal and this is
[28:56] in gated beta at the moment. So you can reach out to your account team if you want to try it. Uh essentially means instead of making this the box bigger we just add more boxes and we add a load balancer in front. Um I would say this
[29:08] is a form of scaling which I would say is the second option. I prefer vertical first and then afterwards horizontal. Uh there is a great talk on this by the lead engineer as well on what we've done to make horizontal scaling smart. I
[29:21] won't go into it. It's quite technical. Now the main thing before you start thinking about scaling the compute um usually it's better to take a step back and and look at the actual problem you
[29:33] have. Right? And I'll give some examples to illustrate um situations I've seen in the past which is there is a situation where a customer is like hey you know my my query is super slow I have a problem
[29:45] where there's a spinner in my app it's taking a lot of time so let me increase the app compute you know it's actually it's not the best decision um because usually if you triage it right the query is probably slow because of the downstream warehouse maybe being unders
[29:58] sized so increasing the app size will not affect the downstream warehouse at all. Um, another example would be if you have a huge list, right, like one million elements and you try and render
[30:10] that in a modern browser, you might see that sluggish, right? You you get trouble scrolling in the UI and someone might feel like, hey, let me increase the app compute. Again, it's probably not going to fix the issue, right? Because it's a browser issue. So the the
[30:23] key point here is that whenever you have a performance issue, you triage it first and you look across the let's say you look at the call stack. So like where am I starting or am I going through and at
[30:35] each point you try and triage okay is this my bottleneck yes or no is this my bottleneck yes or no and once you've done that exercise and you can conf confidently say yes the app compute is my bottleneck then you can go and scale
[30:47] up um now the way I like to do it I like to start from the browser first and I move backwards that's a personal preference you can take any order uh but please don't don't skip this step before scaling up that's the key
[31:01] Now third point is with regards to frameworks. Um I think yeah you don't have to be super like uh dogmatic about this part uh but there are clear impacts on performance when you pick certain frameworks. So take it into account when
[31:13] you start a new project if you decide to go with I won't call out any specific ones. Um some make it easier than others let's say to write performant and good code. um primarily if you look at more strongly typed languages these often uh
[31:26] tend to provide a stronger basis to write faster code let's call it like that if you choose to adopt that early you will have much less issues trying to scale it later not to say it is
[31:38] impossible right you can you can scale a a dash or grado application you just have to probably do more effort than if I were to use something like fastify indojs um these are I would say the primary
[31:50] things you can take into out early stage. If you already have an existing project, you can always look into let's say the guidelines that each framework provides as to how you would scale it. But for example, if your framework is like single threaded, um making the
[32:04] instance larger is not really going to help. And so then you should know that going vertical is not an avenue. You just cross it off the list and you go scale it horizontally instead, for example. Cool. Um, I think I've got three simple
[32:18] uh performance tricks that I wanted to showcase or or mistakes that I've seen uh in in my day-to-day job. Um, they're quite Yeah, you will catch them quite easily often. Let me see if I can.
[32:30] Yes. And I got to find Chrome again. Can you help me out and Oh, awesome. Thank you. Yes. So, you can see I'm a big Windows person. Um, no. Awesome. So,
[32:42] I've got three examples. The first one is usually when customers are building an application, they want to fetch any type of file or image from a unique catalog volume. And this image, let's say that is static, right? It's not continuously changing. And there's two
[32:55] things you can do. You can either on every single time that a user is requesting the image, we can go ahead and fetch it from the volume again or we can, let's say, catch it on the disk of the app itself. And you can see the
[33:07] difference is quite stark. This was a lucky run. Usually it's not a thousand x um but it the difference is is quite realistic. So cing let's say PDFs or or static files that you're serving to your
[33:19] end user that are shared is a very easy way to create a more snappy experience for them. Um second point I wanted to show is with regards to like actually querying a lakebased instance. Right?
[33:31] When you do that usually the advice is to use a connection pool. And you might wonder like why should I use that? A connection pool is like um let's say it's a a set of roads that we have opened and we warmed them up and they're
[33:43] ready to start driving instead of building a new road each time that we make a query. Um now the difference is again probably quite stark hopefully not a thousandx yeah 40x. So main thing here
[33:55] is that when you when you don't have a connection pool every single time you're making a query towards the database you have to create a new connection right that is overhead both on the application layer and also on the postgress side it has to basically create it again it has
[34:08] has a bit of memory overhead and afterwards it's trashed so it's not an ideal form yet what you find is often the the default config that encoding agent might give you if it
[34:20] doesn't have the proper skills is actually a poorly setup connection pool where you might have it constantly creating a few connections and closing them again which is not optimal. Um and second one is even simpler. This is
[34:32] suppose you're making a lot of queries to a a warehouse. Um you can either make these queries you can make the query call sequentially which is like make one query wait and then again make the second query wait or you can uh do
[34:45] something like a a query group where we make all of the queries at once and we wait until they all finish at the same time. You can see again the difference is quite stark where in a sequential case we are like waiting for the total
[34:57] time of all queries whereas in a parallel case we're only waiting for the longest one to finish. Um so these are examples obviously you would you would find many different ways to that you can tune performance in an app main thing is
[35:09] to have the mindset right to be aware and look for these things when you're building your application that you like hey okay I should maybe look at these things and if these things are right then probably things are looking good. Um,
[35:25] great. To talk about the cing part a little bit more, which I showed with regards to the volume and and and file part, there's many different layers and places where you could be cing the data. Um, I think the the most important thing to realize
[35:38] is that the closer you are to the user, let's say, the the faster the experience is going to be. So, you could cage, for example, in the browser itself, right? There's options there. Session storage, local storage. If you do that, then
[35:52] please be careful that you're not cing anything that is, let's say, doesn't belong to this user. So, make sure you only c that is like user specific and then that user is allowed to see. That will be super fast, right? There's not even a network call involved. Whenever
[36:04] they would refresh the page, they would just fetch it from local storage. Now, you can also cage within the app compute, right? The app compute has RAM, it has disk. So anytime when you're like trying to catch a file or you have a list that is like fixed um keeping it in
[36:18] RAM or keeping in memory is actually the fastest way to serve that list. Um second option this is more like if the data set becomes larger and you can't keep it in RAM or it's doesn't look pretty then lake basease is also a great option um to serve that data from right
[36:32] you simply create a table and you're leveraging it as a cage in this case um it will work well I think if you have very high QPS it might not be the ideal target but overall I haven't hit those scenarios myself and the third one I I
[36:46] just basically showed in the demo where instead of fetching files from the volume each time We store them in disk temporarily and we serve them from the app disk directly because it will save us save us an additional network call to
[37:00] hit the volume. Great. I think the main takeaway here is is make sure to profile the bottleneck before like scaling the compute. Uh this should save you yeah some cost and also
[37:13] um making the incorrect decision. Great. So these were the four levers we discussed. We will touch upon them again. I'll I'll give the microphone to another so that he can take the first two again.
[37:25] >> Yeah, just to reiterate right connectivity, pick the engine by by the query shape and not by familiarity. So use lakebased when you have to do these point lookups, use DBSQL, lakehouse when
[37:37] you have to do OLAP queries, analytics, scanning large amounts of data, aggregating and so on. Uh when it comes to identity uh you have UC you want to respect all the permissions use OBO as
[37:50] your default uh whenever users have to see different data. >> Yeah. Thanks An. So on the agent's part right as you mentioned or as I mentioned before um make sure to treat the agent as like one component in a in a broader
[38:03] system. So try and build out the proper setup around it in the app so that you can create a better experience for your end user. With regards to performance, you profile first and then change things. If you adopt that order, you're
[38:15] in for success. So, thanks everyone for listening to our presentation. Hope you'll build great apps after this and uh have a nice conference.

Learn more about the Databricks Data and AI platform.

The information provided herein is for general informational purposes only and may not reflect the most current product capabilities or configurations.