 Hey, everyone in Singapore, welcome to this talk on building full-stab applications with the three-factor architecture. And this three-factor architecture is basically a way for you to use GraphQL and serverless together to build modern slash cloud-needed apps to do a live demo. OK, I think I can do that. But yeah, so anyway, so here's the quick demo that I want to just start off with, so that we have context about what we'll talk about. So here, what I have done is basically set up Hasura on my local machine. That's why you see local host 8080 here. And I also connected it to a database, which is also running locally. It's a Postgres database, and it's completely empty. So this is how when you set up Hasura and you access the console of Hasura through your browser, this is what you would see. So let me go to this data tab and start creating tables, because I'm starting from a fresh database. I don't have any tables. I can create tables through any means, but I'll just use the console here to create tables for me. So let's say I want to create a user table, and I want to give it a few columns like this. Name could be text, and maybe email, which is again text. And I can basically do whatever is possible while creating a table in Postgres, so I can add foreign keys, unique keys, and so on. And as soon as I've added this, I can now switch to graphical, which I'm sure all of you would know by now, I think. Basically, it's a tool where you can try out your GraphQL APIs, and you see complete visibility into what your GraphQL service exposes. And now, so I started with just a table. So with Hasura, what essentially you get is a set of GraphQL APIs automatically generated for you for consumption from the client directly, right? So now you can, for example, I created a user table, that means a field called user is generated, and you can start asking for things there. I did not insert any data, so in fact, I can also insert the data through here, and that would be a mutation. For example, I can do an insert. I can insert multiple objects, or I can insert just one, and I can probably give this a few things, and name is, and I can also get some data back. See, I get the ID, I get everything back, say. So I just inserted a user. This was also auto-generated. I can go back to my previous query here, and if I run it, now I'll see that the user's query actually has one entry here, and I also get powerful filters over the generated API. For example, I can do a simple where clause, say where name is equal to, oops, say name is equal to Thiru, and this would give a result because it does exist, but suppose I change it to Carlos here, I will not get anything because the where query does not match. So this is essentially Hasura, where if you have postgres database, it could be new or existing, you get a set of auto-generated APIs, a very big comprehensive set of APIs automatically for use, and this can be used directly from, say, your back end or even from your front end, because Hasura also comes with an authorization system, so wait for you to embed what kind of users can access what data, and it also, so for example, if you have, say, a Google-based login, then you can use the login information to actually only get data that that particular user is allowed to access. So all these things you can set up in Hasura, and that is the core of the product, right? Now, for three-factor app though, we need few more things, just having just a GraphQL API does not cut it because otherwise three-factor would just be equal to GraphQL, right? So we need more things, but before we get into that, I'll just talk about the other features independently, right? So if you can see this tab over here, it's called events, and this is a way for you to create a kind of an eventing system where whenever something happens to your tables, to your database, you basically call a webhook or an HTTP API with some relevant data, basically related to the event that happened, you can basically send that data to a webhook and you can do whatever you want, business logic, you want to send emails, you want to get notifications. So you can do complex business logic on these events which are basically happening in your database. So let me just quickly give an example for that as well, right? So suppose, for example, after use, I create an event trigger called after user create, right? And I select table, which is, since I only have one table, I can only set two. And I say for whenever an insert happens, send me the data in at this webhook, right? So this is a public API which is used for testing and all that, so I'm just gonna use this to showcase what this feature actually is. So I've basically given an event trigger name and I've said on insert on this table, which is the user table, send me a payload at this HTTP URL, right? So I can go and create an event trigger. Now, if I come back here and if I create, say the mutation, and this time, instead of, suppose I just create a new object, right? Suppose I insert a new user, in this case, it can be Carlos at Carlos.com. And the name also is Carlos, right? Then it goes through, you can successfully create, insert a user and you can also verify this just going back here, the square E, which was previously not written anything, starts returning things. And if I just remove the bare clause as well, I get both the rows. But that's the main point for this is to show the event triggers. So the event trigger that we just created called after user trigger, as you can see here, has under the process events tab has created an event, which you can see here, this was the, basically this was the request that was sent to the webhook that was mentioned. And you don't have to go through the details here, but in a sense what's happening is, there is some metadata associated with the event. And the main thing that you would see is that this was an insert operation and it has an associated data payload. And the data payload has this new information that was basically inserted into the table. So this is what event triggers is. So you can create, you can basically handle events that are happening inside your database and start doing business logic or doing any kind of asynchronous logic after an event in the database has happened. And yeah, so this is kind of independent of just GraphQL, right? This is not just a GraphQL API, this is something you can see, look at it as something independent. But I'll come to why this is important for three factor in a bit. Finally, this is the last thing that I want to show you is this new thing called actions. And actions is a way for you to extend the auto-generated API that you've just seen. So I created a table and that generated lots of APIs for me, but maybe I as a user want to create something new, which has got nothing, which may be related to the tables I have or which may not be related to the tables that I have. It might be just something completely custom, has nothing to do with the database or it has something to do with the database, but not in the way that probably Hasura creates for you, you want something really custom, right? So that is where you would use something like actions. So for example, I create an action, say my custom field. Oh, my bad. So this is basically the first input, which is an action handler, which is again a HTTP web URL. So this is where you would basically write a resolver or write the logic for how to deal with the incoming operation or incoming query that has come that you have defined here. So let me just show that more clearly. So for example, Hasura generated an insert user field, but you want to also add, say a custom thing like, my custom create user, right? We had insert user, but you wanted to create something custom and it can use, again, you can define these things yourself, like what is the input field for this, what is the output type for this, and these things can also be defined here. For example, the input for this is something like access token and this access token could be your Google or token, the Twitter or token, this is just an example, it can be anything and your sample output, so the sample input can be username password or it could be token to be honest and your sample output is basically an access token with which you can do further queries without giving your username passwords, for example. So anyway, so let me go and create this and this was created successfully. So yeah, so coming back to what this handler is, so now you've created these, you're basically created your own schema as a small extension of your schema, but you haven't returned the business logic or the rules for how to actually execute that execute this GraphQL operation and this is what this handler basically does. In this handler, you can write your code so that it actually resolves as a valid response. So if I come back here and I have, if I check the mutation, I'll see that my custom create user is available for me to use and I can give it the input fields that it requires, which in this case is username and password and password like this and I can also get the access token back. This will not work because I have not deployed a proper handler, the handler that I gave there was just a dummy URL. So this is not gonna work, but just to show you what an action is, I think the point is presented with this example. So let me go back now to the slides. So let me just recap what we just saw. So we saw that you can get GraphQL instantly with Hasura. You can have a GraphQL API through whatever means, right? You can write your own thing, you can use some other service, but the important part is you have seen what GraphQL basically is and that you can get GraphQL over your databases instantly. The second thing that you have seen is there is a way for you to capture something called data events and this is what you saw in the events tab that I showed you that whenever some event happens on your database or your tables that you can capture the payload and you can basically do some processing with that data. And finally, the third thing that we saw is also a way for you to look at it as a domain event because you created something custom related to your domain and then you made it execute through your own webhook slash action handler logic. And this can be also seen as a domain event. To make the point further, if you remember coming here that there is a kind option here which can be synchronous or asynchronous. And I think it would be quite natural if this action was actually asynchronous that it's actually creating something called a domain event. But yeah, so this can also be seen as a domain event. In the case of asynchronous it's actually a persisted event. We'll come to that later. But these three things are basically prerequisite for you to start building three-factor apps. Now I've been saying three-factor apps and the topic of this talk is also three-factor apps but what is the problem that it's actually solving, right? So let's get down to that. So this is what a traditional architecture might look like. You have your app here and then you have a layer which I will call as an API layer. And this API layer basically talks to the database. The app does not talk to the database and the API layer could itself be talking to different microservices or third-party APIs and so on, right? So there's a payment microservice. There is, so we are going to build a food delivery app. So there could be a payment microservice. There could be a restaurant microservice and there could be delivery management microservice and so on. So all these three services have to come together to make a successful response, right? So but if you really think about it, is this really scalable? Is this resilient? You have so many components. Is this resilient? Will it, what are the failure conditions and what are the error handling semantics? And if you're building something like this, how do you talk about development velocity? How can you iterate fast? How can you build a prototype quickly and then get to a MVP and actually go to broad and keep making new additions to your application? So these are three questions that you would definitely ask while building a modern application while building an application for the cloud and so on. So let's try to answer these very quite simply. So the first thing is, is it scalable? It really depends on the scalability of the weakest link in the chain, right? So if you have three, four, five components, then the scalability will depend on each of those components and you will be bottlenecked by the weakest one. The second thing, resilience. So you would need a lot of error handling and recovery because any of these components can malfunction or can return some weird error. And since you have already progressed a little bit in the request, you have processed your request little bit partially and you have encountered an error, you need to probably roll back a few changes or you need to somehow backtrack so that you still stay in a consistent state, right? So you will have to handle all these things yourself. You'd have to write code to do all this. And the final thing, the development velocity is that it's easy to build because it's a traditional architecture. There's a lot of literature around it. There's a lot of prior art. You also probably started off with your experience building such, because by definition, traditional architecture is something that everybody learns about. So you would have built something like that and you'd be more comfortable to build something on it. But it's hard to iterate and manage at scale. Suppose you're adding new features every day or your team is big and you have to have independent components being deployed in the application. It becomes really hard to manage fundamentally because it's monolithic in nature, right? So to solve most of these problems, people and not just people, the community has built patterns towards making things more asynchronous in nature, right? Because fundamentally all these problems are happening because of the continuous interlinking or continuous dependencies on each component, which is what makes it monolithic in nature. Although you have different microservices, they're still being called in the same request. So the components might be independent, but the request workflow is still kind of synchronous, right? So the biggest fundamental change that you can do is probably letting go of this assumption that things are synchronous and making things asynchronous. And that is why we try to approach this problem and try to give a solution which kind of builds on these async patterns, which brings me to this event-driven architecture slide and you can see probably a typical architecture with event-driven mechanisms and what event-driven architecture probably looks like. So in this case, there is again an app which is talking to an APL layer. The APL layer is talking to an event system, which is the main driving force here instead of the database, it's the event system. And the event system, let's just think of it as a black box, but as you have seen what events are, you can think of events as basically some payloads, some JSON objects, which you can consume in some way. So this event system basically talks to your microservices, which does payment, restaurant functions and delivery functions and so on. And these microservices in turn either contact the event system directly to create more events or maybe they insert something or do something to the database. So it can go either way. They can talk to the event system or can talk to the database. And finally, the database provides a view of what is the current state. So your application can request for some data and that data can actually come from the database as well. So this is what a typical event-driven architecture looks like, which basically was quite complicated. You might not have imagined things to go from something as this is quite much simpler than what you see here. And which will basically beg the question that why would I even do this? Like this is so complicated. Before we get to that, let's just see what the event-driven architecture basically has. So the first component that you saw is that there is a simple APL layer that creates events, it could be anything. The second aspect is that all communication happens through events. So your APL layer talks to your microservice through the event system and the event and the microservices in turn can create further events if they want to talk to other microservice and so on. So events is the main communication tool in an event-driven architecture. The third thing is that you should have a flexible eventing system itself, which means you might have to send one event to multiple microservices or you want to just send it to few. And there should be a delivery configuration. For example, you want to retry some kind of a failure and so on. So your event system should handle all of this. And finally, the purpose of an event system is not just to store events. It should also deliver it to microservices which handle the events and completes the entire application and so on. So these are the four main things of an event-driven architecture. So having said all this, how does serverless and what is exactly serverless, how does an event-driven architecture relate to this new thing called serverless is what we'll see next. And to start off again, I'll show you a simple hands-on. It's not a proper demo, but this should basically suffice you to give a hands-on feel for what I mean when I say serverless. Basically, you can create a function as shown in the first item here. You can create a function which basically returns a message or a JSON object. And you can use different tools. Serverless is a common thing. There are many providers who have serverless platforms and functions as a service platform and so on. But you can use this tool called serverless which is an open source tool to basically deploy this function here which is defined in this file and you can give it different triggers. In this case, if you give a trigger like HTTP, you would get an endpoint as the return object. So the return value for running this command is going to be this endpoint. And no surprises here. If you curl or if you fetch this endpoint, you will get this message. So all you have to do to get an API, get a function running in the cloud is basically these three steps. So this is the power of serverless. Now, a few more slides about serverless. So what is the big deal of serverless? The big deal is that it's scalable without you having to see any of the infrastructure behind what really went through in providing you with that API. So that means you did no operations, no ops, you had no VMs and no infrastructure to really worry about. And because this has been provided to you as an API, it's the job of the provider to make sure that all the scaling capabilities are built in so that you can use this API in low throughput environments where there are like few users, but you should also be able to use it in high throughput environments where you have like hundreds and thousands or even millions of users. So the scaling is built in into the platform. So you just write the code in and deploy and you basically don't have to worry about scaling. And the second thing, this is slightly more complex, is that serverless platforms are essentially built on event-driven notions. So in this case, like we gave the trigger as HTTP, what really happens in the serverless platform is that an incoming request is kind of like an event trigger for running that function that you defined. So this is something slightly deeper into how serverless infrastructures usually work, but they are event-driven in nature, in which case you can basically use all the things that you could do with events. For example, like you can retry on failure and so on. So if you send a request, maybe through HTTP and you could be waiting on the response even though the underlying, even though the platform might have trouble maybe executing a code and so on, but you'd never really see those errors as a consumer. So this is kind of what makes serverless infrastructure and serverless-based platforms quite resilient and we'll see how, why that matters in a bit. So coming back to the event-driven example, and I think it's just left with a few more slides. So coming back to the event-driven example, suppose you have a table in your application which is like this. Like you have an ID you have created at, you have the user who created it, and you have a few Boolean columns which basically gives you the status of the order. So maybe the order is valid, is it paid, is it approved by the restaurant, is an agent assigned for the delivery and so on. So this is a small example of how you might have, how you might build a food ordering application and this could be a data model for that. And going back to the traditional architecture and we can see that this was basically the architecture here which could now actually in an event-driven, a scalable and resilient, in a resilient system might change to something like this where a database is actually creating events for you and the events are basically calling the serverless functions and the serverless functions are writing it back to the database. This could be a typical example of how you would change some synchronous architecture here to something asynchronous here where the event system is basically doing all the work and the event system should have the properties of scaling and being resilient and so on. Let's see what would be the flow of stake. Like I have just given the architecture diagram but what is the flow really going to be like, right? And this is basically a diagram to demonstrate that. So if a new order comes in, you would have all these Boolean values set to false. So it's not valid, it's not paid, it's not approved, it's not, no agent is assigned for that. But the new order would create a new record in your orders table, for example. And like we saw in the first demo that that could create an event which is handled by Lambda here or Lambda is another way for calling. Lambda for AWS is basically their service platform but Lambda in general has now become a symbol for any kind of functions in the service or a serverless platform. So here in this serverless function you could validate the order and probably set it to true if the order is valid which could then create another event because you basically mutated the table. This could create another event which checks for payment and sets if the payment is done, sets to true on which case you can create another event which is to see if the restaurant kind of approves the order and so on. So this is basically a simple workflow of how you can move state, how you can go from a new order to a completed order in an event-driven way where you can learn more about this in this blog post here. But there's still one problem, right? You have made all this event-driven async and so on. There's still one problem as a front-end developer that all those things are happening in the background but what do I show the user? Like when stuff happens asynchronously how should your app basically get updates? That is where real-time GraphQL comes into picture and real-time GraphQL I'm sure you've had some... In this meetup, in this meetup you've heard about real-time GraphQL already it's a way for you to get data which is in the back-end systems in real-time maybe over web sockets and so on so your app can show updates and this is the missing piece which basically solves the problem when things are happening asynchronously in your application. And this finally brings us to what a three-factor architecture really is it's an architecture where you use a real-time GraphQL or APLA or you have a reliable eventing system and you run business logic in serverless systems and the final architecture diagram probably looks like this I'm using Hasura as implementation of this it could be your own implementation so your app basically talks to say Hasura or your real-time GraphQL engine via subscriptions it makes changes via mutations events are created through the database in the case of Hasura because I showed you event triggers the event system is also kind of driven off the database but I also showed you actions which kind of lets you create events outside of the database so it could be custom events so you create events which are then delivered with your respective serverless functions which are running your logic for your application and they are again talking to Hasura by either making GraphQL mutations or making any kind of table modifications and so on so this is the three-factor architecture the event-driven architecture that you saw initially kind of reduces more simply to this architecture and this is why this is much simpler with all the good properties of event-driven architectures so the final demo here of a quick one is this order app where I'm going to put a name here so I'm going to say GraphQL Singapore HungryUser I'm going to place a new order so let's try this Indian thing here maybe you get it in Singapore as well and if I just create an order I can see basically this application which shows its state so first you have order validation which is completed but in the middle I have to make a payment so let me just make a payment and once the payment happens the rest of the processes happen in the background asynchronously so the restaurant approval process would have happened and then the driver assignment process would have happened this is basically an implementation of the workflow that I just showed you and finally if you are interested in learning more about this this has its own page a very simple page which just describes the architecture in more detail which brings me to the end I think I have slightly gone overboard with the time but yeah so this is the final slide thank you all very much for having me and just a small thing here you might notice a GraphQL Asia sticker here we are having GraphQL Asia in India in February I think Carlos has much more information than just this poster here so yeah if you have any more questions about whether if you want to speak or you want to attend do talk to Carlos about it thank you very much