WEBVTT 00:00.000 --> 00:10.000 All right, so next song is the editing and the audio. 00:10.000 --> 00:11.000 Thanks. 00:11.000 --> 00:16.000 Thank you. 00:16.000 --> 00:18.000 I'd like to see so many of you here. 00:18.000 --> 00:20.000 I didn't expect this amount of attendance here, 00:20.000 --> 00:23.000 but it's good to see so many people interested in a topic like 00:23.000 --> 00:25.000 David Drake, Stephen Aki, I tools. 00:25.000 --> 00:28.000 Let me say a few words about myself. 00:28.000 --> 00:30.000 I am, oops. 00:30.000 --> 00:32.000 This is not working. 00:32.000 --> 00:34.000 Then I am going to use the keyboard. 00:34.000 --> 00:35.000 My name's Eric. 00:35.000 --> 00:37.000 I'm a software engineer at Profilment Tools. 00:37.000 --> 00:40.000 And in my free time, I'm an open source maintainer in the GraphQL space. 00:40.000 --> 00:42.000 I mainly work on GraphQL in Python, 00:42.000 --> 00:46.000 so that includes the libraries like Graphene and Strawberry. 00:46.000 --> 00:50.000 And let me say a few words about Strawberry first. 00:50.000 --> 00:52.000 Strawberry is a GraphQL framework, 00:52.000 --> 00:54.000 which enables you to easily build GraphQL applications in Python. 00:54.000 --> 00:56.000 It was created by Patrick Aminio. 00:56.000 --> 00:59.000 And it follows an implementation first approach, 00:59.000 --> 01:02.000 which is a subset of code first, GraphQL libraries. 01:02.000 --> 01:04.000 And it's basically inspired by data classes, 01:04.000 --> 01:06.000 and it really makes you implement a GraphQL way, 01:06.000 --> 01:09.000 GraphQL API in a very pathonic way. 01:09.000 --> 01:12.000 And Strawberry offers integrations for Django, 01:12.000 --> 01:14.000 Cicral, Cami, Pedantic, and more. 01:14.000 --> 01:16.000 And if you've been in the Python space, 01:16.000 --> 01:19.000 and you see Python, Django, and Cicral, 01:19.000 --> 01:21.000 you probably know where this is headed a bit. 01:21.000 --> 01:23.000 Just our curiosity, who here has used, 01:23.000 --> 01:25.000 or who is using Python actively. 01:25.000 --> 01:27.000 In an API project, that's nice. 01:27.000 --> 01:30.000 And who here has used GraphQL in Python before? 01:30.000 --> 01:31.000 Okay, not so many. 01:31.000 --> 01:35.000 Maybe I can inspire a few of you to give it a try in the future. 01:35.000 --> 01:37.000 But let's get to the topic, 01:37.000 --> 01:39.000 and have a look at today's API development 01:39.000 --> 01:42.000 and how many of you probably develop your APIs. 01:42.000 --> 01:44.000 And that is using an API first approach. 01:44.000 --> 01:48.000 So basically, you create a concept for something 01:48.000 --> 01:50.000 you want to add to your application. 01:50.000 --> 01:52.000 In this case, we have an example, 01:52.000 --> 01:56.000 API over user, and a post, for example, for block application. 01:56.000 --> 01:59.000 And you can see you have a couple of types, a user type, 01:59.000 --> 02:02.000 which has an ID, and the user name, and the list of posts, 02:02.000 --> 02:05.000 as well as a post type, which consists of, of course, 02:05.000 --> 02:09.000 the title, the content, and you can also fetch the author for a post. 02:09.000 --> 02:12.000 And down here, we enable the user, 02:12.000 --> 02:16.000 or enable any API consumer to fetch users from the API. 02:16.000 --> 02:19.000 This case by ID, and it will turn a user. 02:19.000 --> 02:22.000 If you want to start off when doing sort of API first, 02:22.000 --> 02:24.000 you create a contract, you say, this is our API. 02:24.000 --> 02:26.000 So the consumers know how to use it, 02:26.000 --> 02:28.000 and then you start implementing it. 02:28.000 --> 02:31.000 So basically, instead of implementing this API, 02:31.000 --> 02:33.000 it would look something along the way. 02:33.000 --> 02:34.000 It's lines of this. 02:34.000 --> 02:37.000 Very similar, as you can see, you can see the user class. 02:37.000 --> 02:40.000 You can see the post class, and then to resolve the posts of a user. 02:40.000 --> 02:42.000 You add to certain data resolvers. 02:42.000 --> 02:46.000 Like over here, you call the post service to load the post of a user 02:46.000 --> 02:48.000 with the given user ID. 02:48.000 --> 02:50.000 And you do the same for your queries. 02:50.000 --> 02:54.000 So down here, you add a result to get a user by its ID. 02:54.000 --> 02:57.000 And all of this is manual, you have to add it step by step. 02:57.000 --> 03:00.000 And usually, in order to be able to do that, 03:00.000 --> 03:02.000 you need to implement the methods that are called here. 03:02.000 --> 03:06.000 In this case, we have a service layer, including a post service, a user service, 03:06.000 --> 03:13.000 and this service layer, again, needs to access the database below that 03:13.000 --> 03:15.000 to actually fetch the data. 03:16.000 --> 03:20.000 So after declaring all of this, you again have to make another declaration 03:20.000 --> 03:22.000 step and declare some database models. 03:22.000 --> 03:26.000 In this case, I'm using a Django flavor to just declare the models. 03:26.000 --> 03:29.000 And over here, we have the models for a user and post again. 03:29.000 --> 03:31.000 As you can see, they're very similar. 03:31.000 --> 03:36.000 And they, again, describe how the data is mapped to SQL Arcami, 03:36.000 --> 03:39.000 and to SQL SQL database, I'm sorry. 03:39.000 --> 03:45.000 And yeah, if you map the two SQL, it would look something like this. 03:45.000 --> 03:50.000 And if you remember the schema I showed you, it's very similar, 03:50.000 --> 03:52.000 especially in this overview. 03:52.000 --> 03:55.000 And the question I always have when working on applications like these, 03:55.000 --> 03:57.000 where you have a strict layer separation, 03:57.000 --> 04:00.000 doesn't it feel kind of redundant to declare your types two or three times 04:00.000 --> 04:02.000 with minimal differences in the fields? 04:02.000 --> 04:06.000 Okay, I'm not going to argue against clear separation of concerns 04:06.000 --> 04:08.000 and applications that's an important pattern, 04:08.000 --> 04:10.000 and it has its sense. 04:10.000 --> 04:12.000 But in very quite heavy applications, 04:12.000 --> 04:16.000 just pulling your username through with the same type through all of your layers 04:16.000 --> 04:18.000 and your application can sometimes feel exhausting, 04:18.000 --> 04:20.000 and it can take up a lot of your development time. 04:20.000 --> 04:24.000 You could use for other valuable things like actual features. 04:24.000 --> 04:27.000 So I wonder, doesn't it feel redundant to do it a bit? 04:27.000 --> 04:30.000 And let's examine this further a bit at first, 04:30.000 --> 04:35.000 by looking at the control flow of such an application as the one I've shown you. 04:35.000 --> 04:38.000 So right here on the left side we have a sample query, 04:38.000 --> 04:40.000 which just gets the user of the ID one 04:40.000 --> 04:43.000 and touches all of the posts associated to that user. 04:43.000 --> 04:46.000 And this query is usually passed by a GraphQL execution engine, 04:46.000 --> 04:50.000 which then calls the appropriate data resolvers to you have defined in your schema. 04:50.000 --> 04:52.000 So in our case, it was the user resolver. 04:52.000 --> 04:54.000 And then, next the user resolver, 04:54.000 --> 04:58.000 it calls the user service to actually fetch this user 04:58.000 --> 04:59.000 from the database. 04:59.000 --> 05:02.000 And then the data flow goes on to the object relational method, 05:02.000 --> 05:04.000 the Django models, I've just shown you, 05:04.000 --> 05:07.000 to generate a SQL query to actually fetch the user from the database. 05:07.000 --> 05:11.000 So in this case, we can see select ID username from users is one. 05:11.000 --> 05:16.000 So next up, we need to fetch the posts connected to the user over here. 05:16.000 --> 05:19.000 So once again, after the user is resolved, 05:19.000 --> 05:22.000 neglected execution engine goes ahead and resolves the posts, 05:22.000 --> 05:23.000 fields of the users. 05:23.000 --> 05:26.000 And again, here the user post resolver is called. 05:26.000 --> 05:29.000 It invokes the post service to get all of the posts from the database. 05:29.000 --> 05:34.000 And again, another SQL query over here is formulated. 05:34.000 --> 05:39.000 So when you build such an application, 05:39.000 --> 05:41.000 basically you need all of your service layers. 05:41.000 --> 05:43.000 You need your database access layer, 05:43.000 --> 05:44.000 and you need your schema layer. 05:44.000 --> 05:46.000 And then you need to glue it together. 05:46.000 --> 05:49.000 Using a lot of glue code, right? 05:49.000 --> 05:52.000 Calling all of the services from each other. 05:52.000 --> 05:56.000 And this is where database revenue APIs come in. 05:56.000 --> 05:59.000 Because the paradigm has just shown you, 05:59.000 --> 06:03.000 basically has a workflow from the left side to the right side. 06:03.000 --> 06:05.000 You start with an API schema, 06:05.000 --> 06:07.000 and you end up at a database schema, 06:07.000 --> 06:11.000 which fits the kind of API you want to provide to your consumers. 06:11.000 --> 06:14.000 And as we've just seen, for many cases, 06:14.000 --> 06:17.000 like the one over here, the database schema already contains 06:17.000 --> 06:20.000 enough information to infer an API schema from it. 06:20.000 --> 06:22.000 Right? We have the database types. 06:22.000 --> 06:25.000 For example, strings, we know primary keys are IDs in our schema. 06:25.000 --> 06:26.000 We know the relationships. 06:26.000 --> 06:28.000 For example, by foreign key relations, 06:28.000 --> 06:31.000 we know which types are connected to each other 06:31.000 --> 06:33.000 in our GraphQL schema. 06:33.000 --> 06:36.000 So basically, in database revenue APIs, 06:36.000 --> 06:39.000 we want to go from this to this, 06:39.000 --> 06:42.000 and actually infer the API schema 06:42.000 --> 06:44.000 for what we have in our database schema. 06:48.000 --> 06:51.000 In this case, for our strawberry-based approach, 06:51.000 --> 06:53.000 we would want to take this Django model. 06:53.000 --> 06:55.000 We formulated for our database schema, 06:55.000 --> 06:59.000 and it somehow generated the GraphQL schema out of it. 06:59.000 --> 07:01.000 And for strawberry Django, it's easy 07:01.000 --> 07:03.000 as replacing the code with this. 07:03.000 --> 07:06.000 So now over here, you can see a lot of things have changed. 07:06.000 --> 07:09.000 I removed all of the fields from the user and post type, 07:09.000 --> 07:12.000 and we changed the annotation up here to a strawberry Django type. 07:12.000 --> 07:15.000 And in that case, it tells strawberry Django 07:15.000 --> 07:18.000 to actually take all of the fields from the post model 07:18.000 --> 07:20.000 and put them into the GraphQL schema. 07:20.000 --> 07:23.000 There are some static methods, for example, 07:23.000 --> 07:26.000 for the foreign keys, for the chart fields, and for the text fields, 07:26.000 --> 07:28.000 which are mapped to appropriate GraphQL scalers 07:28.000 --> 07:30.000 in the GraphQL schema. 07:30.000 --> 07:32.000 And the most magical thing about this 07:32.000 --> 07:34.000 is that you don't have to care about data 07:34.000 --> 07:35.000 resolving any more either. 07:35.000 --> 07:37.000 Because now you can just plug in 07:37.000 --> 07:40.000 that strawberry Django field into your query type, 07:40.000 --> 07:42.000 and everything we have done before 07:42.000 --> 07:44.000 to fetch a user by its ID or to fetch a list of users 07:44.000 --> 07:48.000 is automatically handled for you by the framework. 07:48.000 --> 07:51.000 I'll show you that in a second. 07:51.000 --> 07:53.000 Basically, having a look at our control floor 07:53.000 --> 07:57.000 from before again, all of this glue code you had to write before. 07:57.000 --> 07:59.000 You can remove it with strawberry Django. 07:59.000 --> 08:02.000 You don't need a user service or a specific user 08:02.000 --> 08:03.000 resolver for your example anymore. 08:03.000 --> 08:06.000 It will be handled for you by the framework. 08:06.000 --> 08:09.000 Instead, you plug it in, and you get some new features 08:09.000 --> 08:11.000 like query optimizations. 08:11.000 --> 08:14.000 So if you look at the query before, 08:14.000 --> 08:17.000 you have two separate queries which are called 08:17.000 --> 08:18.000 and that is kind of inefficient. 08:18.000 --> 08:20.000 You want to use or leverage the query planner 08:20.000 --> 08:23.000 that is provided to you by the database 08:23.000 --> 08:24.000 as much as possible. 08:24.000 --> 08:26.000 Like you cannot write a more efficient query 08:26.000 --> 08:27.000 than any of your business logic, 08:27.000 --> 08:30.000 then it's already present in any database you're using. 08:30.000 --> 08:33.000 And frameworks like strawberry Django 08:33.000 --> 08:35.000 are able to read the GraphQL query 08:35.000 --> 08:38.000 to analyze what's field you request it 08:38.000 --> 08:41.000 which relationships need to be joined onto the query 08:41.000 --> 08:44.000 and generate a corresponding SQL query 08:44.000 --> 08:47.000 out of it to optimize the way you fetch your data. 08:47.000 --> 08:49.000 And it's all automatically done in the background 08:49.000 --> 08:52.000 you don't have to do anything for it. 08:52.000 --> 08:54.000 The next feature you just get for free 08:54.000 --> 08:56.000 is a pagination interface. 08:56.000 --> 08:59.000 Basically, if you know about cursor-based pagination, 08:59.000 --> 09:01.000 it's all implemented there. 09:01.000 --> 09:04.000 You could also add other pagination styles and 09:04.000 --> 09:07.000 flavors and have that automatically generated for you. 09:07.000 --> 09:10.000 Another nice feature is automated filtering 09:10.000 --> 09:13.000 because at least I also have a lot of struggles 09:13.000 --> 09:16.000 with adding a lot of filters to my API. 09:16.000 --> 09:18.000 Because it's kind of annoying. 09:18.000 --> 09:19.000 It's very simple. 09:19.000 --> 09:22.000 You have to edit in all of the layers in your usual code base 09:22.000 --> 09:25.000 and with sorry Django, all the filters that are available 09:25.000 --> 09:28.000 on your SQL model are automatically available in your API 09:28.000 --> 09:29.000 if you choose to do so. 09:29.000 --> 09:33.000 For example here, I can filter all use by a user name 09:33.000 --> 09:37.000 that starts with Eric and then that will work. 09:37.000 --> 09:40.000 One of the nice things about strawberry Django 09:40.000 --> 09:44.000 is that you can automatically create track mutations. 09:44.000 --> 09:47.000 Basically create update, delete mutations, 09:47.000 --> 09:51.000 which insert the entities based on the database schema. 09:51.000 --> 09:55.000 So with this, you have already covered a large part 09:55.000 --> 09:57.000 of basic application functionality. 09:57.000 --> 10:00.000 Like reading data, reading lists of data 10:00.000 --> 10:02.000 and modifying the data. 10:02.000 --> 10:04.000 But many applications have custom requirements. 10:04.000 --> 10:07.000 You don't want any type to have any filter available 10:07.000 --> 10:11.000 or maybe any field in your database should be accessible. 10:11.000 --> 10:13.000 For example, a password hash, if you start in your database 10:13.000 --> 10:16.000 for some reason, shouldn't really be accessed accessible 10:16.000 --> 10:17.000 in the API. 10:17.000 --> 10:20.000 That is where customization plays an important role. 10:20.000 --> 10:24.000 And shortly, Django, it's really easy to do that. 10:24.000 --> 10:27.000 Over here, you can see our post type again. 10:27.000 --> 10:29.000 And I've added the fields back. 10:29.000 --> 10:33.000 However, I haven't added the back exactly as in the example 10:33.000 --> 10:34.000 in the beginning. 10:34.000 --> 10:36.000 You can see here, I added the title fields. 10:36.000 --> 10:39.000 But I annotated the type of the title fields as auto. 10:39.000 --> 10:41.000 And auto just tells the framework 10:41.000 --> 10:45.000 to resolve the type based on the schema type in the database. 10:45.000 --> 10:49.000 I wanted to modify the content field to a type called Markdown 10:49.000 --> 10:52.000 just to signify that this requires some additional 10:52.000 --> 10:53.000 parsing. 10:53.000 --> 10:55.000 And I can do it as simple as changing the type here. 10:55.000 --> 10:57.000 And the framework will automatically 10:57.000 --> 11:00.000 still resolve it back to the database type. 11:00.000 --> 11:03.000 Another thing I can do is use other nice features of strawberry 11:03.000 --> 11:05.000 like automatic handling of permissions 11:05.000 --> 11:07.000 and add them to the fields in the database. 11:07.000 --> 11:09.000 And it will be resolved for you. 11:09.000 --> 11:10.000 So it's really fluent. 11:10.000 --> 11:14.000 The kind of customization you can do from a purely database 11:14.000 --> 11:18.000 oriented type to some type with a little bit of business logic. 11:18.000 --> 11:21.000 You choose how much you want to add. 11:21.000 --> 11:24.000 And the next important part after customization 11:24.000 --> 11:26.000 is extension of your API. 11:26.000 --> 11:29.000 Maybe sometimes the database type is not enough. 11:29.000 --> 11:31.000 You need some custom logic on top of it. 11:31.000 --> 11:34.000 That's why accessibility is very important to do easily 11:34.000 --> 11:35.000 in such frameworks. 11:35.000 --> 11:39.000 So this example, you can see that I added a resolver for a post 11:39.000 --> 11:41.000 caption to all the post five. 11:41.000 --> 11:44.000 And as you can see, you can just use the data provided 11:44.000 --> 11:46.000 in the database model inside of these resolvers. 11:46.000 --> 11:49.000 For example, here the caption's just the title with the current date. 11:49.000 --> 11:52.000 And I can access all of the database fields in these resolvers 11:52.000 --> 11:55.000 and do not have to worry about any missing data, 11:55.000 --> 11:57.000 not being present. 11:58.000 --> 12:01.000 So far so good. 12:01.000 --> 12:05.000 We've now talked about an extensible approach 12:05.000 --> 12:09.000 to generate your objective graphical schema from a database schema. 12:09.000 --> 12:10.000 Right? 12:10.000 --> 12:12.000 You are starting off with a strawberry code base. 12:12.000 --> 12:14.000 You have your web server hooked up. 12:14.000 --> 12:16.000 And you have all the configuration already present. 12:16.000 --> 12:18.000 And then you plug in strawberry Django. 12:18.000 --> 12:22.000 And the Django or M to actually infer any models. 12:22.000 --> 12:26.000 And infer this database schema from those models. 12:26.000 --> 12:30.000 And then up cases where you don't actually want that. 12:30.000 --> 12:31.000 Or you don't need that. 12:31.000 --> 12:32.000 You just have your database. 12:32.000 --> 12:35.000 And you want to get a graphical schema that actually enables you 12:35.000 --> 12:37.000 to do what you want. 12:37.000 --> 12:41.000 And this case is actually very important because in many, 12:41.000 --> 12:43.000 there's a lot of use cases nowadays. 12:43.000 --> 12:45.000 For example, grab your APIs. 12:45.000 --> 12:48.000 I use an LLMs or AI use cases in general. 12:48.000 --> 12:50.000 And you just want access to the data, 12:50.000 --> 12:52.000 but not to the raw database. 12:53.000 --> 12:57.000 And this is where tools like Post Graphile come in very handy. 12:57.000 --> 13:01.000 Because they enable you to create a GraphQL schema just 13:01.000 --> 13:04.000 from a Postgres database without any additional framework 13:04.000 --> 13:05.000 or wiring. 13:05.000 --> 13:06.000 You have to do around it. 13:06.000 --> 13:07.000 You just install it. 13:07.000 --> 13:08.000 And it works. 13:08.000 --> 13:12.000 But still it's as extensible as the approach I've shown you before. 13:12.000 --> 13:18.000 And what Post Graphile does is it reads the Postgres schema 13:18.000 --> 13:21.000 that is stored in the database to automatically generate the API. 13:21.000 --> 13:23.000 So you don't even have to define any models. 13:23.000 --> 13:25.000 It's automatically read from the schema. 13:25.000 --> 13:28.000 And similar to Strawberry Django, 13:28.000 --> 13:31.000 Quad mutations, and all of the nice logic and the nice extras 13:31.000 --> 13:34.000 like filtering, pagination are added automatically for you. 13:34.000 --> 13:39.000 And you can extend it even further using a right variety of plugins. 13:39.000 --> 13:42.000 I want to give you a little comparison. 13:42.000 --> 13:44.000 It's going to be a bit harder to read, 13:44.000 --> 13:48.000 but between Strawberry Django and Post Graphile. 13:48.000 --> 13:52.000 So on the one hand, in Strawberry Django, you see I added some documentation 13:52.000 --> 13:53.000 to the Post type. 13:53.000 --> 13:57.000 And I also added some other information. 13:57.000 --> 13:59.000 For example, I might have excluded a field here. 13:59.000 --> 14:03.000 And all of this is handled via smart text in the database in Post Graphile. 14:03.000 --> 14:08.000 So up here, for example, you can see the first tag is a comment 14:08.000 --> 14:10.000 which I added on the Posts table. 14:10.000 --> 14:13.000 And basically this will also lead to the Posts table being documented 14:13.000 --> 14:15.000 in the GraphQL schema. 14:15.000 --> 14:18.000 When I want to exclude fields, again, it's a smart tag. 14:18.000 --> 14:20.000 It's the omit tag. 14:20.000 --> 14:24.000 And here, I am extending a certain private field from the post type 14:24.000 --> 14:27.000 by omitting it for reading from the API. 14:27.000 --> 14:30.000 And you can do the same for filters, pagination, 14:30.000 --> 14:33.000 or actually relationships, and maybe even whole types in your database, 14:33.000 --> 14:36.000 schema that you don't want to expose in the API. 14:36.000 --> 14:39.000 And also, this is logic is possible to be implemented. 14:39.000 --> 14:42.000 Like down here, the caption of the post, 14:42.000 --> 14:44.000 is just represented via a SQL. 14:44.000 --> 14:47.000 We are post based function, which again, we solve status. 14:47.000 --> 14:51.000 And you can automatically plug that into your schema. 14:51.000 --> 14:56.000 So let's compare the two approaches on a basic level. 14:56.000 --> 14:58.000 Both are very extensible. 14:58.000 --> 15:01.000 You start with a set of features that every application needs, 15:01.000 --> 15:05.000 and you are good to go in minutes. 15:05.000 --> 15:09.000 But the main difference is that strawberry agenda really requires you 15:09.000 --> 15:12.000 to have your strawberry up around it, 15:12.000 --> 15:15.000 and your Python ecosystem of tools to get it going. 15:15.000 --> 15:18.000 Our post graph is up and running right away. 15:18.000 --> 15:22.000 You can, however, extend it and extend it with no JS code 15:22.000 --> 15:25.000 to actually add more business logic, add more custom features, 15:25.000 --> 15:29.000 and extend the schema, but it just works right out of the box. 15:29.000 --> 15:32.000 Another big difference is that post graph 15:32.000 --> 15:35.000 are really focused on having business logic in the database, 15:35.000 --> 15:38.000 utilizing as much of the database as possible, 15:38.000 --> 15:42.000 what strawberry Django is really focused on the features 15:42.000 --> 15:45.000 that are present within an ORM. 15:45.000 --> 15:49.000 So basically the database schema and the relationships you define. 15:49.000 --> 15:53.000 And another difference is that post graph is just made for post graphs, 15:53.000 --> 15:57.000 and strawberry Django supports all SQL implementations, 15:57.000 --> 16:00.000 which are supported by Django or RAM. 16:00.000 --> 16:03.000 But if you ask me a nowadays world, 16:03.000 --> 16:06.000 it's probably always best to use post graphs for most use cases, 16:06.000 --> 16:10.000 and it's not meant much of a mis to not have support, 16:10.000 --> 16:14.000 for example, my SQL in those applications. 16:14.000 --> 16:17.000 So let's talk about a few common pitfalls. 16:17.000 --> 16:20.000 I get a lot of questions about migrations. 16:20.000 --> 16:24.000 For example, many people are concerned 16:24.000 --> 16:27.000 when coupling your database a bit tighter to your schema 16:27.000 --> 16:29.000 on how to do migrations. 16:29.000 --> 16:32.000 And actually my answer to that is pretty straightforward 16:32.000 --> 16:34.000 when you're doing migrations in an application, 16:34.000 --> 16:36.000 especially in a distributed system. 16:36.000 --> 16:39.000 You also have to worry about not breaking things 16:39.000 --> 16:41.000 based on the consumers of that database. 16:41.000 --> 16:44.000 You have to be very careful if you're removing fields, 16:44.000 --> 16:47.000 changing field types, and you have to do that incrementally. 16:47.000 --> 16:49.000 For example, if you change the name of a field, 16:49.000 --> 16:51.000 you have to keep the old name there. 16:51.000 --> 16:54.000 And with tools like strawberry Django and post graph file, 16:54.000 --> 16:59.000 it's very easy to add smart tags or custom logic to change field names 16:59.000 --> 17:01.000 and map to the old fields first, 17:01.000 --> 17:03.000 and after the migrations completed, 17:03.000 --> 17:06.000 you have to make an API breaking change. 17:06.000 --> 17:10.000 Because while the GraphQL schema is met to the database schema, 17:10.000 --> 17:12.000 there are ways to customize it, 17:12.000 --> 17:16.000 and there are ways to actually direct the data to the point 17:16.000 --> 17:19.000 where you want it, and to use the database columns 17:19.000 --> 17:22.000 that you're actually interested in. 17:22.000 --> 17:27.000 This was mostly focused on GraphQL for now. 17:27.000 --> 17:30.000 Since I'm working GraphQL, I'm a bit biased, 17:30.000 --> 17:33.000 but I'm probably telling you the best way to do this is via GraphQL, 17:33.000 --> 17:37.000 but there's great tools out there to do this in REST APIs as well. 17:37.000 --> 17:42.000 First example is Postgres, which enables you to build a REST API 17:42.000 --> 17:45.000 from your Postgres databases. 17:45.000 --> 17:47.000 For example, the Python ecosystem, 17:47.000 --> 17:51.000 there's a two like SQL model, which will also decrease the amount of workload you have 17:51.000 --> 17:55.000 or the amount of layers you have to go through to map a database model 17:55.000 --> 17:58.000 to an API model that is actually validated. 17:58.000 --> 18:02.000 So, some of the database-driven APIs 18:02.000 --> 18:05.000 derive an API schema from the database schema, 18:05.000 --> 18:11.000 and they generate API types from the native types in your database. 18:11.000 --> 18:15.000 And tools like Postgres file can leverage native database features 18:15.000 --> 18:19.000 to use your technology as efficiently as possible, 18:19.000 --> 18:24.000 without having to duplicate any types throughout the layers of your applications. 18:24.000 --> 18:27.000 And by doing that, you are able to iterate rapidly. 18:28.000 --> 18:31.000 I told you, you just have to start the tool and the API is going, 18:31.000 --> 18:33.000 and then you can start with customization. 18:33.000 --> 18:35.000 Usually, when you're developing an application, 18:35.000 --> 18:37.000 you're adding a new feature, for example, a post feature, 18:37.000 --> 18:40.000 you first need to edit everywhere, you code it, 18:40.000 --> 18:44.000 and then, at some point, you can integrate it with Post GraphQL, 18:44.000 --> 18:49.000 or Strawberry Django, everything is there immediately. 18:49.000 --> 18:52.000 So, when we're talking about database-driven API tools, 18:52.000 --> 18:56.000 we should also talk about when not to use database-driven API tools. 18:57.000 --> 18:59.000 And for me, the answer is, 18:59.000 --> 19:02.000 it really depends on the kind of application you're building. 19:02.000 --> 19:05.000 And I really see it as a spectrum from pure-cut applications 19:05.000 --> 19:09.000 on the one hand, which just have data you put into the database, 19:09.000 --> 19:13.000 that's created, update, and delete mutations to modify that data, 19:13.000 --> 19:15.000 and on the other hand, there's very behavior-centric apps, 19:15.000 --> 19:18.000 very domain-driven applications with lots of business logic 19:18.000 --> 19:20.000 custom code inside. 19:20.000 --> 19:23.000 And I think for pure-cut applications, it's obvious. 19:24.000 --> 19:26.000 Try it out, see if it works for you, 19:26.000 --> 19:28.000 and it can save you a lot of time, 19:28.000 --> 19:33.000 and bring you a lot of features, make your API greater than it ever used to be. 19:33.000 --> 19:38.000 However, I don't think it only is only a good choice for pure-cut applications. 19:38.000 --> 19:43.000 I think the separation point is somewhere around here, 19:43.000 --> 19:46.000 because from my experience, even very behavior-centric applications, 19:46.000 --> 19:50.000 with a lot of domain logic, contain a large part that is purely cut 19:50.000 --> 19:52.000 for many types that are in the application. 19:52.000 --> 19:55.000 And for this part of the application, you can still benefit largely 19:55.000 --> 19:58.000 from using a database-driven API tool. 19:58.000 --> 20:03.000 So, why should you use database-driven API tools? 20:03.000 --> 20:06.000 Basically, you can utilize your technologies effectively, 20:06.000 --> 20:10.000 save a lot of time, and get going with minimal boilerplate or blue code 20:10.000 --> 20:12.000 in your application. 20:12.000 --> 20:15.000 Additionally, you can make sure your database schema 20:15.000 --> 20:18.000 is at all times consistent to your API schema, 20:18.000 --> 20:20.000 where you want it to be consistent, 20:20.000 --> 20:23.000 and you don't have any duplicate types you need to work on. 20:23.000 --> 20:26.000 And this, all in all, enables you to innovate rapidly, 20:26.000 --> 20:30.000 and build nice tools faster and easier than ever before. 20:30.000 --> 20:31.000 Thank you. 20:31.000 --> 20:33.000 Over here, you find the QR code to my LinkedIn, 20:33.000 --> 20:35.000 feel free to contact me with any questions, 20:35.000 --> 20:38.000 and here you can find two links to the docs of the tools I presented. 20:39.000 --> 20:48.000 Any questions? 20:48.000 --> 20:50.000 Yes? 20:50.000 --> 20:53.000 There are any, or, are you aware of any kind of authorization 20:53.000 --> 20:56.000 or access to the management? 20:56.000 --> 21:01.000 So, I haven't gone too deep into this because the lack of time, 21:01.000 --> 21:05.000 but I'm post graph, how you can do authorization also within Postgres. 21:05.000 --> 21:06.000 There's a good feature. 21:06.000 --> 21:08.000 I'll ask Benji back there for more details. 21:08.000 --> 21:10.000 He's a maintainer of post graph files. 21:10.000 --> 21:13.000 And post strawberry, for strawberry, Django and strawberry, 21:13.000 --> 21:15.000 and all those database tools, 21:15.000 --> 21:19.000 it's very easy to just plug it into the existing strawberry provision system 21:19.000 --> 21:21.000 that we have going. 21:21.000 --> 21:22.000 Yes? 21:22.000 --> 21:23.000 Yes? 21:23.000 --> 21:25.000 You talk about migrations. 21:25.000 --> 21:27.000 What do you know about provision? 21:27.000 --> 21:28.000 Is it possible? 21:28.000 --> 21:29.000 How is it used? 21:29.000 --> 21:30.000 Okay. 21:30.000 --> 21:33.000 So, since this talk is more focused on GraphQL, 21:33.000 --> 21:37.000 the general recommendation in GraphQL is to not version your entire schema, 21:37.000 --> 21:42.000 but to keep your schema evolving and back what's compatible is much as possible over time. 21:42.000 --> 21:45.000 There's no real versioning strategy that I have in mind, 21:45.000 --> 21:48.000 like right from the back, it would depend on the specific use case probably. 21:48.000 --> 21:52.000 General recommendation I can give is to version by field, 21:52.000 --> 21:55.000 so basically at a new type, next to your old type, 21:55.000 --> 21:58.000 if you want to make breaking changes to the API schema. 21:58.000 --> 21:59.000 Yes? 22:00.000 --> 22:02.000 Yeah? 22:02.000 --> 22:05.000 Are you going on a little bit to the opposite direction of what GraphQL, 22:05.000 --> 22:08.000 or is you want to do an extra from the database? 22:08.000 --> 22:11.000 And I want to try to kind of attempt the end, 22:11.000 --> 22:14.000 I always end up having to sort of choose to give a dive version 22:14.000 --> 22:16.000 and then I can use the tools anymore, 22:16.000 --> 22:18.000 and I have them in interest. 22:18.000 --> 22:20.000 I like the question, 22:20.000 --> 22:23.000 because when many people first discover GraphQL, 22:23.000 --> 22:25.000 they think, oh, nice, it's a big database. 22:25.000 --> 22:28.000 I can use to access all of my data without limits. 22:28.000 --> 22:30.000 And this is not what GraphQL should be. 22:30.000 --> 22:33.000 These tools might enable you to do that. 22:33.000 --> 22:35.000 What I maybe didn't mention here enough 22:35.000 --> 22:38.000 is that you should still stick to certain best practices, 22:38.000 --> 22:42.000 do not expose everything, do not expose every relationship 22:42.000 --> 22:44.000 and every field in your database schema, 22:44.000 --> 22:47.000 expose the data that is necessary to deliver your application 22:47.000 --> 22:49.000 the way you want it to be delivered. 22:49.000 --> 22:52.000 And that is the big advantage of these tools. 22:52.000 --> 22:54.000 You are able to build a database, 22:54.000 --> 22:56.000 like a database access tool, 22:56.000 --> 22:58.000 out of them, because they are so powerful, 22:58.000 --> 23:00.000 but with great power comes great responsibility, 23:00.000 --> 23:03.000 and after all, at some point, 23:03.000 --> 23:05.000 you really need to, 23:05.000 --> 23:06.000 if you stick to best practices, 23:06.000 --> 23:08.000 you will not run into these risks. 23:08.000 --> 23:12.000 Any more questions? 23:12.000 --> 23:14.000 Then, thanks everyone. 23:14.000 --> 23:16.000 There's some stickers. 23:16.000 --> 23:18.000 Thank you. 23:18.000 --> 23:20.000 Thank you. 23:20.000 --> 23:22.000 Thank you. 23:22.000 --> 23:24.000 Thank you.