 I'm so excited. That's the second time that I'm way better than a commercial break. Like let's just start with the serverless functions. Why? Why even wait? So I am thrilled to be here today. My voice is going to hold out for one more amazing session here at.net.com. I'm getting over a little bit of a cold if you can hear to my voice, but I'm so excited I will be just as durable as the functions that we're going to talk about. So last year at.net.com, I did a session talking about durable functions and some of the patterns that you can do. I'll do a slight refresher on that for those who might not have seen last year's one. But what I really want to talk about today is durable functions 2.0 and some of the stateful patterns that you can now do for.net, doing serverless compute in the cloud to let you do things like stateful entities, actor like patterns, orchestrations that unlock an entire new world of scenarios that you can start to get into. So to start with, as mentioned before, I'm Jeff Holland. I'm a program manager on Azure serverless focusing on Azure functions. So today we're going to start by doing a little bit of an overview of what durable functions is. We're going to talk about some of those new patterns, specifically durable entities, go over some examples and scenarios. And if you have questions, be sure to tweet hashtag.net.com and I'll answer those at the end as well. So I'll make sure to keep time for questions, but please participate, ask questions as we go so that I can answer them here live. So thinking about functions, I apologize for those who might not be familiar with Azure functions already. I'm going to kind of make some assumptions that you're aware of what a serverless function is at least, even if you haven't already used one. And traditionally, when you think about functions, there's oftentimes paired with some qualifications about functions like, oh, they're stateless, they're very short lived. So if you want to do a pattern like what I'm showing here, just a really simple, you know, an event happens like, hey, we add a customer, whenever we add a customer, we need to create a record for them in a CRM database and then we need to send them a welcome email and then we need to update some SQL database, right? You have like three tasks that need to happen. The way that traditionally you'd have to build that is like what's showing behind me, right? This idea where you have function one, drops it in a queue, function two triggers, does its little short processing, drops it in a queue and then hits function three. And it's totally fine. You can do it that way, but it's a bit cumbersome as a developer or an operator to have to write this decoupled code as these kind of independent functions, managing it, deploying it, looking at how many customers I'm adding in the health of that pipeline can be challenging. So what durable functions let you do is this an extension to Azure functions that can be installed in as a NuGet package. And it will enable you to write this in code for ways using code to describe more stateful and long-running stuff. So here, this is an example of an orchestration. It's the same logic I was showing you before where I'm going to call function one, then I'm going to call function two, then I'm going to call function three. That's what I've described here in code. But here, rather than me having to manage the queues or mentally map how things might be happening, I've actually been able to write this as code as a special type of function as a durable function. Now, this entire orchestration might take 30 minutes. It might take three days. That's totally fine. Durable functions is going to do it all for me as this nice extension. And let me describe it and monitor it and manage it as code. So here I can absolutely see what's happening. Oh, yeah, function one, function two, function three. If an exception happens, you'll notice I even have things like a try and a catch block so that I can catch exceptions and handle them. So it's this nice pattern that I'm able to do. Excuse me. As I mentioned, I'm going to be durable. I'm going to make it through this. All right. So what are some of the patterns that you can do with durable functions? And I mentioned before the kind of one I spent some time about last year was talking about orchestration. So I have my orchestrator function. It's calling into my activity functions. These are other functions in the same app. And I can chain them together. But I can also do other patterns, right? So sequencing is the one we've talked about. You could do fan out and fan in with durable functions. Imagine a scenario where, hey, every week there's going to be a report. I'm going to get a batch report. And for every single record in that report, I want to go execute a function. And rather than me having to kind of manually drop stuff in queues, durable does it for me. I could just describe this as like a for loop and say, hey, for each record, call this function and durable functions is going to do that for you. External events correlation kind of an example here I like to think about is imagine that you're hiring a new employee and there's three events that have to happen, right? They have to upload their driver's license. They have to upload their social security information and maybe they have to upload some form. And what I want to have happen is wait until all three of those things have happened and then continue, maybe fire a third function that says, hey, you're done, you've uploaded all you need to do with durable functions. So you can write in code away for a function that waits for those three external events, waits for all of them to happen and when all three have happened, we'll continue on also written in .net code just like the code I showed you earlier. Long running operations is a powerful pattern as well where maybe you actually want to monitor something. I did a sample a few months ago, which was pretty simple. It's also in our durable functions docs, which was, hey, tell me when the weather is going to be nice over the next six hours. So you could kick off a function and every 10 minutes, it's going to pull the weather and say, like, hey, is it going to rain? Is it going to be sunny? I live in Seattle, so we really need durable functions just to let us know when it's going to be sunny outside. And so this function is going to monitor the weather for a few hours, maybe a day, and as soon as the weather is nice, it sends me a text message. So the idea where I have this kind of long running function where I'm monitoring the weather, I can describe that as a durable function as well. Asynchronous work, this is another powerful pattern where maybe I want an HTTP triggered function, one that can be triggered on an HTTP request, but maybe that HTTP request is going to take five, 10 minutes to process its work. And I don't really want to call the function and have the thing that's calling it, keep that request alive for those five or 10 minutes. Oftentimes, like if it's from a mobile app, it's very common that I'm going to have a hiccup in my connection. It might disconnect after three or four minutes. It's not a very scalable pattern. So with durable functions, I can say, hey, start the function, fire it, but then return back immediately with a status endpoint and be like, hey, I got your request. Check back in a few seconds so let me know what my progress is. So you can kind of have like this progress API through durable functions where the function might take 10 minutes to process that HTTP request, but my clients just check the status. Like, hey, are you done yet? Nope. Are you done yet? Nope. Are you done yet? Yep. I'm done. Here's the result. Awesome. Great. Super seamless pattern. Just a few lines of durable function code. And then finally, human interaction. Maybe I have a approval, right? I submit a document. I need to wait for Jeff to approve it. I need to wait for Seth to approve it. Once both of them have approved it, then, you know, submit it to the final result. So these are just a few of the patterns that are more stateful in nature, are more long running in nature, that if you're using just serverless out of the box or as your functions out of the box, it might be like, how do I solve these? And durable makes it really trivial, which is code samples and examples. And in fact, all of the patterns I've shown here, if you go to the durable function documentation, which I'll link to at the end of the presentation, we have code samples and examples for doing all of these. Now, how does durable functions work behind the scenes? And I want to illustrate it with this slide. So I have here and I apologize. The color is a little bit hard to note. In this gray box, I have my durable function code and it's just a really simple, durable function orchestrator. It's just going to call the say hello function and pass in the value world. Now, behind the scenes, how durable functions is working is you just write this little bit of code here, that gray box up top. And durable functions, this extension to your Azure function is going to interact with a storage provider like Azure Storage to monitor and maintain the state for you. It's going to keep what's called an execution history so that it knows what step it's at, what step to do next, still enabling you to do like scaling to zero. So for example, if I was doing an approval workflow and it's like, hey, I need to wait for Seth to approve a document before I can continue. You're not paying for the two, three, four hours or four days where your function is not running and you're just waiting for approval. Your function can actually scale to zero. And when Seth approves the document, it wakes up and continues on. So that's all happening because of the state management behind the scenes. So let's walk through it now. Let's say I trigger off this function. I say, hey, start my orchestration and the function wakes up and it's going to start evaluate the first line of code. So it's going to say, all right, create a new list outputs and it will get to the next line and durable functions is going to see this await word. And when it sees the await word, it knows that there's some activity, some task that it needs to perform. Now, as I mentioned, because it might be resuming from a previous state, it might have crashed from a previous state. The first thing it's going to do is it's not actually going to evaluate this code. It's going to go ask durable functions. And it's going to say, hey, have I already done this? Have I already said hello to world? So in this case, the durable function asks the execution history. And it's like, hey, have I already said hello to the world? And the execution history is like, no, you haven't done this yet. It's like, OK, cool, I know that's what I need to do then. So it's going to go ahead and schedule this work. It's going to drop a message in a queue that's managed completely for you. You're going to say, hey, we need to say hello to the world. And after that, your durable function stops. It's done. It's like, hey, I scheduled my task. Now I'm going to wait to get triggered again. Now at this point, your activity function, your function that's actually going to do the work, your say hello function, it had some work scheduled for it. So it's going to wake up. It's just been triggered. It's got work scheduled for it. So it wakes up, it triggers, it says, hey, my orchestrator wanted me to say hello to the world. So the function is going to do its work. It's going to update the execution history table. You'll notice I visualize that here. So, hey, I did my work. I said hello to the world and then it shuts down. Now, when that happens, the orchestrator gets triggered again. Now, here's the really important part to note. When the orchestrator starts again, it doesn't resume from the middle, right? There's not really a way to just start from line 52. So what's actually going to happen is the durable function is going to start from the top again. It's been triggered. It's going to first evaluate that first line of code, right? Create a new list. Now, it's going to get to the second line. And as I mentioned, it's going to say, hey, I need to await something. I need to await saying hello to the world. And it's going to make that same check. It's going to say, hey, execution history. Have I already done this thing? Have I already said hello to the world? And in this case, I have, right? In the history table, my activity function did its work. It created its outputs. And it's like, yeah, you actually said hello to the world. There's a lot of hello world. So then the function is like, great, I'm going to go to the next line. And in this case, the next line is just return outputs. But you could imagine if I call another function and another function, this pattern kind of continues where I'm scheduling work. The work gets scheduled. I'm updating the results in the history table. And then my function spins up again and starts again. So all this happens for you behind the scenes. You don't have to worry about this kind of execution history song and dance. You just write that really simple code that I showed earlier that looks a little bit like this, but behind the scenes, that's what's happening. It's using storage, it's queuing, scheduling work, and it's replaying that orchestrator and rehydrating the state every time it plays. Now, that's durable functions all up. Let's now talk about durable functions 2.0. And as the name implies, 2.0 is better. It's great. It's new. It's exciting. Durable functions 2.0 is currently in preview. We just shipped the beta 2 package a few weeks ago. So what are some of the improvements that are coming to durable functions? Well, the first one that I'm the most excited about is this durable entities pattern that we're going to go into in just a second. If you've done any actor programming before, like Aukka.net or or leans or service fabric, you might see some similarities in this durable entities pattern. Another one that we've shipped as part of durable 2.0 is the ability to make resilient HTTP requests from an orchestrator. So an orchestrator being like, hey, call function one, call function two, call function three. You can now say, oh, now make an HTTP request. You can even add authentication to that HTTP request. So maybe you have a durable function that's going to call a few Azure APIs. You can do all those Azure APIs and use like a managed identity to authenticate those requests all within a durable function. Plugable state providers. So previously, durable functions just worked on Azure storage. We now have a method to swap in different state providers. Maybe you don't want it to be Azure storage. Maybe you actually want to be Redis because you're going to be running these durable functions on premises or in Kubernetes or you want it to be Event Hubs or Kafka. We've created a new pattern so that you can plug in different state providers. Your code doesn't need to know about it, but behind the scenes, it can use some different state providers to take advantage of maybe better throughput, disconnected environments, et cetera. We're shipping a Roslin analyzer that will actually evaluate your code and Visual Studio or VS Code as you write it to let you know of common pitfalls. Like, hey, the code you wrote here isn't deterministic. And when it does a replay, it might end up getting in a weird state. Our analyzer can detect that and do the little squiggly lines for you, which is fantastic. We've also just made some nice improvements around the interfaces and testability so that you can more easily write unit tests, implement interfaces for your durable functions. So this is some of the goodies that are there. But let's actually spend the next few minutes diving into durable entities. Now, what is a durable entity? Again, traditionally, you think about functions, you think about stateless and short lived. These are stateful functions that can be long running in their state. So let's take a very simple example, a counter. Let's pretend that I'm creating the next Fitbit or Apple Watch. Everyone's going to get a device and I want to track the amount of steps that someone has taken. So I really need some state for each user. It's a counter. Now, let's look at how you could write that using durable functions in this new entity pattern. So this is an example of a durable entity. This is an entire function app right here. This is all the code that I would need for my function app. And really, it just looks like a class because that's kind of what it is. It's a counter class and my class has properties. I have the count property, which is an integer, which I'm going to set to zero initially. I can increment the count. I can decrement the count. Obviously for Fitbit, you don't really reduce steps when you walk backwards, but a counter can go backwards. And here I'm just saying like, hey, when I increment, increment count by one, decrement count by one, I could terminate an instance of a counter. Maybe I have Jeff's counter, I have Chris's counter, I have Seth's counter. Maybe I want to destroy one of those counters. I don't want to keep the state anymore. In fact, if you've written functions before, the only thing here that might look a little familiar is this line at the bottom, which is like, hey, I have a function, which I'm going to call counter. But all it's saying is map this to a durable entity of class counter. That's the only code I have to write here for a function app. And Azure functions with durable functions will now turn this into a counter. So let's check that out now. I have here in Visual Studio Code an example of that counter. This is the same counter we were just looking at. The only thing I've added here is I've injected in a logger. You can inject in bindings as well. You can inject in your own custom services. But here I'm just injecting in a logger, but it's still that counter. This is the entire code for my function app right here on the screen. Now, what's amazing here is just like any function app. Let's go ahead and start and debug this project. Again, all it is is these 25 lines of a class definition saying, hey, I want you to keep track of a serverless counter. So it's going to spin that up. It's going to run the Azure functions runtime on my machine right now. And because I have the durable functions extension installed, in fact, if I open my CS Proj file, you can see here, I pulled in that beta two package of the durable task extension. As my function app spins up, it's going to recognize that this is a durable entity. This is a stateful function, and it's going to let me interact with it. Now, there is a durable SDK that I could use to interact with that counter inside of my code if I wanted to, or durable entities exposes a direct REST API so I can perform operations on my entities, get the state of my entities directly over HTTP without having to create like an HTTP trigger if I didn't want to. So my functions now running and here I have some HTTP requests that I'm going to use to call this entity, right? So it's running on local host 771. Here's the path to that REST API. I'm saying, hey, call durable task and an entity. And here I have counter. Now, why does it say counter here? Because that's the name of my class. That's the name of the function that I created called counter. In this part right here in the path, this is where I put in the ID of the counter, right? If you think about this idea of a stateful function, I might not just have Jeff's counter. I might have Seth's counter and Chris's counter. So here's where I can define the different counters that are going to be running. Each of these might have a different count step, right? Different steps for each person. So let's go ahead and try to get the steps for Jeff right now. And when I call it, it's going to process. And actually right here, what it's returning back is a 404 not found. That's because this is a brand new function, a brand new storage account. I've never run it before. I've never done an operation on Jeff. He's never taken a step. So it doesn't actually exist yet, which is fine. Let's go ahead and do an operation on the Jeff counter. Let me move this out of the way. So here I have a post request that I'm going to make. And here I'm going to say increment the counter for Jeff. Now, why is it say increment here? And that's because if I come back here to my counter code, it is because here I defined a method called increment, right? So it maps to the method that I defined. So I'm going to say, hey, increment, which does count plus plus. So let's go ahead and send that request. It says accepted. Let's send it a few more times. Let's take a few more steps and send, send, send. I think I hit that four times, maybe five times. Now let's do that first call again. Get the current state of Jeff. And when I call that here, I get back a 200 OK. And you'll notice now it actually knows the count for Jeff is five. Now what's cool here is I could shut down my machine. I could restart my machine. I could close everything down. I could spin it back up again, make this same call. And it's going to remember, oh, yeah, I have the state for Jeff and the count is five. I could publish this to the cloud running as an Azure function. It's only going to run and bill me when it's actually being invoked. But I could call this in three weeks time and it's going to remember the count for Jeff is five. So this is a powerful pattern that lets me now represent state, keep that state around, manipulate that state and have some operations on that state. Completely serverless, right? So all the benefits of functions, massive scale, only pay for when it's running, but in this case, using durable functions in this new stateful entity pattern. So where are some of the places that this might come in handy? There's a lot. I have another example I won't run into now, which is like imagine that it's .netconf and I have a bunch of sessions. Right? I won't run the sample, but I will show it because I think it's a good one to visualize. Imagine here that I have sessions. So I have a session class, like a session at .netconf. Every session has attendees, number of people who are viewing it. Maybe they can submit reviews or evaluations, which is going to be a dictionary with the string and double string being the attendee name, double being the score. And I can also submit an evaluation, which is a method to submit an eval. Here I'm going to pass in an evaluation, which I've defined here. It's just an attendee and a score, as I mentioned. I can add those together. I can even get back in aggregation, which is like, hey, give me back the average score for this session. I could now deploy this class, this durable entity as a function app, have it processing and maintaining the state for every session happening at the conference, maybe multiple sessions in parallel and durable entities is going to maintain the state for me, storing all this in Azure storage behind the scenes. But I, as a developer, haven't had to worry about wiring that out. In fact, I get nice guarantees here, too, where imagine that, you know, I tried to increment my counter a hundred times at the exact same second, I will get guaranteed single threaded for one instance of the counter so that my counter will increment 100 times, right? It won't have race conditions as well. So there's some cool stuff here. The last pattern I want to show with durable entities, this gets a little bit more advanced. So hopefully, hopefully you've been able to follow along so far. It's actually a pattern that I've come up against a lot running serverless functions. So let me walk you through this scenario here. Imagine I have a simple architecture like this. I have Azure event hubs that I'm sending thousands of events to every second. Those events are triggering a function and that function maybe needs to update some data in a database like Cosmos DB or SQL. Well, behind the scenes as these thousands of events are coming in, my function is actually probably going to scale, right? It's going to scale to many, many instances. And the problem comes in. What happens if there's an outage or some issue with my database downstream? What if my function is triggering this whole time? It's trying to update these records in a database, but those calls are failing. And people can get nervous in this because your function keeps scaling, it keeps triggering, but it's just hitting failure after failure after failure after failure. So what I wanted to implement is a circuit breaker pattern where ideally I have something that is monitoring the state and the health of my circuit. So here it's the same architecture, but you'll notice I've just added in the stop light here, which is green right now, which is supposed to be saying, hey, this is healthy. And what I want to have happen is that if I start getting a bunch of exceptions, like maybe a hundred exceptions, I actually want to set this to red and stop triggering my function. But how do I do that? That can actually be complicated to solve for, especially noting that my functions are going to be scaling across these concurrent instances. Well, this is where durable entities comes in. I'm going to deploy a durable entity, which will be monitoring the state of my function circuit, that stop light. And whenever one of my functions hits an exception, I want it to send a signal up to that entity. And it's up to my circuit entity, that stateful function, to do some aggregation math to figure out, is this healthy or not? And if it notices that I get maybe a hundred exceptions in the same second, it's up to the durable entity to stop the trigger, to turn it off. Right? So that's what I wanted to build. And in fact, there's a sample on GitHub that I'll link to in a second that does exactly that, where I have a durable entity that has the state of the circuit open or closed, and you can add a failure to it. Any of my functions can say, hey, I hit an exception. And I just have here some code. I'm not going to dig into it right now, where I'm saying, you know what, if I ever have more exceptions, in my case, it's like 50 exceptions within a 30 second window, then I want to go ahead and break the circuit to turn it off. And in that case, I just have some code that disables this function app. So let's actually test it out now. The last thing I want to show here, I have here running in the Azure portal. This is my event hub triggered function. And right now it's running, it's happy. And let's go ahead and publish now a thousand poison events to this function. So I'm going to send bad, very bad events. Let's go ahead and publish now a thousand bad events. So I know I'm going to hit my exception threshold. Let's pretend that these are all database failures. And here, if I come back here to my live metric stream, we should see here in just a moment, assuming that, yep, it's sending those messages. My function is going to wake up and it's going to start triggering. And it's going to hit exception after exception after exception. And what's powerful here is that after I hit that threshold of exceptions, my durable entity is actually going to fire and disable my function app. Now I'm refreshing and now it doesn't look like it's triggered. I hope I've hooked up to the right. Oh, there we go. All right. Might have been some Wi-Fi hiccups there or wherever else. So I'm now online. I see some failures processing. You actually notice actually right away, my exception rate started to climb. It's hitting a lot of exceptions here. And normally this is where I'd get really nervous, right? If I had a thousand requests coming in every second, this exception rate is just going to grow and grow. But you'll notice it actually just dropped off pretty quickly. And the reason it dropped off is because here I hit my threshold of exception and it's actually disabled. It stopped my function app. So I had this durable entity that was keeping the state of this function, monitoring the health of it, it hit enough exceptions in that window that that stateful function was able to then go turn off my other function. So kind of an advanced pattern here, but just trying to give you the idea of how you can use these stateful functions to unlock patterns that traditionally would be really hard that you want state for, maybe an aggregation, but with durable entities become super simple. So before I move to questions, these are just some resources for you to be aware of. If you're interested in using Durable 2.0, check out this link to check out the docs for Durable Functions 2.0. There's a number of samples like how you could use durable functions to create a Twitter service or a rideshare service that you can check out at the second link and finally that circuit breaker sample, the code that I used to do that last example of disabling a function. That's here as well. If you have any questions, reach out directly on Twitter as well. More than happy to help. But with that, I'm going to see if there's any questions that have come in during this time. So we'll turn it back over here to see if there's anything that's popped up. Yeah, awesome. Thank you so much, Jeff. That was really, really cool. We have some questions. So the first one is, when is ASP.NET Core 3.0? When will it be available for Azure App Service? Yep. So I believe it should be there, if not now, very, very soon. I was on an email thread yesterday where once it went GA, we have to go update kind of our entire fleet of machines and make sure that they have 3.0. I believe it should be there now. Obviously, there's a few ways to run App Services, so you can run App Services in a container, which would just work out of the box. But I believe now you can take a .NET 3.0 function app, deploy it to App Services, and it should work. If it's not available now, it should be imminent. As I mentioned, there's been some very chatty threads to make sure we're ready to go. Awesome. And then here's another one. So where can people get your Azure Functions t-shirt? Isn't this amazing? I love this is my favorite shirt. I'll move my laptop so you can look at that. It's the ASCII art for the function run time. So I will tell you, we are printing a bunch of them right now, because it's a hot commodity. If you can make it to Microsoft Ignite, we're going to have thousands of them. So come to our booth there. If you can't make it, try to grab us at some other conference. We'll make sure to bring them. Obviously, .NET Conf is a digital conference, so it's harder to distribute them through this live stream, but they're coming. And I'm glad you appreciated it. I love the shirt. Yeah, so here that everyone go to Ignite, and that's where you'll get those t-shirts. Yeah. And we have another question. What languages support the durable functions framework? Yeah, fantastic question. So .NET supports it. Obviously, it's what I showed. JavaScript is the other one that you can write these durable orchestrations in. Right now, we're working on getting JavaScript to work with these new entity features I just showed. So some of the two features I've been talking about are only exposed through the .NET SDK right now. JavaScript is being worked on right now as well. But we're working on Python support. I don't know if we've actually said that publicly before, but we are working on Python support as well. So stay tuned over the next few months for any updates and news around Python for these durable functions. OK, great. And we have another question. Adorable functions or Logix apps? When should I use what? Yeah, that comes up very often. If you've used Logic Apps before, they also let you create these orchestrations specifically. Some of the big differences, Logic Apps is a declarative visual designer. So when you write a Logic App, you have these different connectors and you can have, you know, step one, call step two, call step three, doing similar things that a durable function orchestration can do. Honestly, what I think it comes down to for a lot of folks is personal preference. Some people want to describe these orchestrations in code. Some people like this declarative nature or the visual designer of Logic Apps. So that's a big one. There's a few other ones where I'd say it's a little bit easier. If you want to leverage one of the over 200 connectors that Logic Apps has, use Logic Apps. If you're only orchestrating functions, maybe durable is a little bit nicer for you there, though Logic Apps can do it great as well. Some of these other patterns, like we talked about stateful entities, that's really going to be durable only. So there definitely is some overlap. Personal preference is big there. I'm a fan of both. I'll use Logic Apps for some things, durable for others. It's kind of like, hey, do I want one of these connectors? Do I want this visual designer? Or am I just going to write some simple logic in code directly? Cool. And here's another one from Simon. When will it be possible to change the runtime of an Azure App Service or Function Service to .NET Core 3.0? Yeah, so this is slightly different from the first question in that you can write like an ASP.NET Core 3 App and deploy it to App Service. But functions, like when I showed you the function code, it's its own kind of SDK. It's almost like its own flavor of ASP.NET in some ways. That does not support 3.0 yet. We're underway working on it right now. There's an announcement in our GitHub repo currently next month, so October, we'll have Azure functions in .NET Core 3 available to try out and becoming generally available early next year. So stay tuned for that as well as to be able to write these functions in .NET using .NET Core 3 App Services, as I mentioned, if you're just deploying a web app using ASP.NET Core, that's much sooner. But a function app using .NET Core 3 is next month for preview. Cool. And I think we have time for one more question. So the last one is, how much data can you store in the state pool pattern? Is there a limit of how many users can I store the amount of steps? For how long will this data get stored? Am I paying for the stored data? So it's really up to the storage account behind the scenes for some of the limits. There's no limits with the framework itself. We'll just use your Azure storage account. You will be paying for that storage. So by default, we'll keep it around indefinitely. If you have a bunch of data in there, we have SDKs to help you kind of clean up old instances or old entities if you want to keep it clean, but by default, we'll stick them in an Azure storage account. As long as your Azure storage account has the room for it, you can keep your state there. If you want kind of more state or you need higher throughput than Azure storage is able to provide, that's where I mentioned some of those plug-able providers will come in. But you will be paying for the storage costs of all the states. So like my counter example, if I open my storage account right now, there's going to be a blob that says like Jeff's counter, the value is five. I'm going to be paying some whatever one hundredth of a cent for that state. If I had bigger state, I'd be paying more. All right, awesome. Thank you so much, Jeff.