{"id":340910,"date":"2021-05-27T07:23:23","date_gmt":"2021-05-27T14:23:23","guid":{"rendered":"https:\/\/css-tricks.com\/?p=340910"},"modified":"2021-05-27T07:23:25","modified_gmt":"2021-05-27T14:23:25","slug":"rethinking-postgres-in-a-post-server-world","status":"publish","type":"post","link":"https:\/\/css-tricks.com\/rethinking-postgres-in-a-post-server-world\/","title":{"rendered":"Rethinking Postgres in a Post-Server World"},"content":{"rendered":"\n

Serverless architectures have brought engineering teams a great number of benefits. We get simpler deployments, automatic and infinite scale, better concurrency, and a stateless API surface. It\u2019s hard to imagine going back to the world of managed services, broken local environments, and SSHing into servers. When I started doing web development, moving from servers in a closet to rackspace was a revolution.<\/p>\n\n\n\n

It\u2019s not just hosting and how we deploy applications that have changed under this new paradigm. These advantages of serverless have presented challenges to the traditional MVC architecture that has been so ubiquitous. Thinking back to those early days, frameworks like Zend, Laravel, Django, and Rails were incredible productivity boosters. They not only influenced the way we built applications, but also the way we think about solving problems with the web. These were your \u201cmajestic monoliths\u201d and they solidified the MVC pattern as the defacto standard for most of the web applications we use today.<\/p>\n\n\n\n

In many ways, the rise of microservices and with it the idea of hexagonal architectures (aka ports and adaptors) led naturally to this new serverless world. It started as creating and hosting standalone APIs organized by a shared context that were still backed by the classic frameworks we already knew and loved.<\/p>\n\n\n\n\n\n\n\n

The popularity of NodeJS led to the express framework where we now had a less rigid microframework enabling us to more flexibly organize our code. The final metamorphosis of this pattern is individual pieces of business logic that can be executed on demand in the cloud. We no longer manage machines or even multiple API servers. Each piece of business logic only exists when it is needed, for as long as it\u2019s needed and no longer. They are lightweight, and you only pay for the individual parts of your application that get used.<\/p>\n\n\n\n

Today, we hardly realize there is a server at all–even the terminology, serverless, is a misnomer designed to highlight just how far we\u2019ve come from the days of setting up XAMP or VirtualBox and Vagrant. The benefits are clear, the hours saved, the headaches avoided, and the freedom to just solve business problems with code bring building software closer than ever to the simple act of writing prose.<\/p>\n\n\n

The Problem<\/h2>\n\n\n

The classic MVC frameworks codified not only the pattern of working in three distinct tiers (data, application, and presentation) but also the technology for each. You were able to choose some options at each layer, for instance Postgres or MySQL as the data layer, but the general idea is these decisions are made for you. You implicitly adopt the idea of convention over configuration.<\/p>\n\n\n\n

Postgres as a data layer solution makes a lot of sense. It\u2019s robust, fast, supports ACID transactions, and has over thirty years of development behind it. It is also open-source, can be hosted almost anywhere, and is likely to be around for another thirty years. You could do much worse than stake your company’s future on Postgres. Add to that all the work put into integrating it into these equally battle-tested frameworks and the story for choosing Postgres becomes very strong.<\/p>\n\n\n\n

However, when we enter a serverless context, this type of architecture presents a number of challenges particularly when it comes to handling our data.<\/p>\n\n\n\n

Common issues include:<\/p>\n\n\n\n

  1. Maintaining stateful connections:<\/strong> when each user is a new connection to Postgres this can max out the number of connections Postgres can handle quickly.<\/li>
  2. Provisioned scale:<\/strong> with Postgres we must be sure to provision the right size database for our application ahead of time, which is not ideal when our application layer can automatically scale to any workload.<\/li>
  3. Traditional security model:<\/strong> this model does not allow for any client-side use and is vulnerable to SQL injection attacks.<\/li>
  4. Data centralization:<\/strong> while our application may be deployed globally, this is of little use when our database is stuck in a single location potentially thousands of miles from where the data needs to be.<\/li>
  5. High operational overhead:<\/strong> serverless promises to free us from complexity and remove barriers to solving business problems. With Postgres we return to needing to manage a service ourselves, dealing with sharding, scaling, distribution, and backups.<\/li><\/ol>\n\n\n\n

    Traditional systems like Postgres were never designed for this purpose. To start, Postgres operates on the assumption of a stateful connection. What this means is that Postgres will hold open a connection with a server in order to optimize the response time. In a traditional monolithic application, if your server had to open a new connection every single time it requested data this would be quite inefficient. The actual network request would in many times be the primary bottleneck. By keeping this connection cached Postgres removes this bottleneck. As you scale your application you will likely have multiple machines running, and a single Postgres database can handle many such connections, but this number isn\u2019t infinite. In fact, in many cases, you have to set this number at the time of provisioning the database.<\/p>\n\n\n\n

    In a serverless context, each request is effectively a new machine and a new connection to the database. As Postgres attempts to hold open these connections we can quickly run up against our connection limit and the memory limits of the machine. This also introduces another issue with the traditional Postgres use case, which is provisioned resources. <\/p>\n\n\n\n

    With Postgres we have to decide the size of the database, the capacity of the machine it runs on, where that machine is located, and the connection limit at the time of creation. This puts us in a situation where our application can scale automatically but we must watch our database closely and scale it ourselves. This can be even trickier when we are dealing with spikes in traffic that are not consistent in both time and location. Ultimately by moving to serverless we have reduced the operational overhead of our application layer, but created some increased operational overhead in our database. Would it not be better if both our application and our data layer could scale together without us having to manage it?<\/p>\n\n\n\n

    The complexity required to make traditional systems like Postgres work in a serverless environment can often be enough to abandon the architecture all together. Serverless requires on-demand, stateless execution of business logic. This allows us to create lighter, more scalable programs but does not allow us to preserve things like network connections and can be slowed down by additional dependencies like ORMs and middleware. <\/p>\n\n\n

    The Ideal Solution<\/h2>\n\n\n

    It\u2019s time we begin thinking about a new type of database, one more in line with the spirit of serverless and one that embraces iterative development and more unified tooling. We want this database to have the same automatic, on-demand scale as the rest of our application as well as handle global distribution that are hallmarks of the serverless promise. This ideal solution should be:<\/p>\n\n\n\n

    1. Support for stateless connections with no limits.<\/li>
    2. Auto-scaling both for the size of the machine and in the size of the database itself.<\/li>
    3. Be securely accessible from both the client and the server to support both serverless APIs as well as Jamstack use cases.<\/li>
    4. Globally distributed so data is closest to where it is needed always.<\/li>
    5. Free of operational overhead so we don\u2019t add complexity managing things like sharding, distribution, and backups.<\/li><\/ol>\n\n\n\n

      If we are truly to embrace the serverless architecture, we need to ensure that our database scales along with the rest of the application. In this case, we have a variety of solutions some of which involve sticking with Postgres. Amazon Aurora is one example of a Postgres cloud solution that gives us automatic scalability and backups, and gives us some global distribution of data. However, Amazon Aurora is hardly easy to set up and doesn\u2019t free us from all operational overhead. We also are not able to securely access our data from the client without building an accompanying API as it still follows the traditional Postgres security model.<\/p>\n\n\n\n

      Another option here are services like Hasura, that allow us to leverage Postgres but access our data by way of a GraphQL API. This solves our security issues when accessing data from the client and gets us much closer to the ease of use we have with many of our other serverless services. However, we are left to manage our database ourselves and this merely adds another layer on top of our database to manage the security. While the Hasura application layer is distributed, our database is not so we don\u2019t get true global distribution with this system.<\/p>\n\n\n\n

      I think at this point we should turn toward some additional solutions that really hit all the points above. When looking at solutions outside of Postgres we have to add two additional requirements that put the solutions on par with the power of Postgres:<\/p>\n\n\n\n

      1. Support for robust, distributed, ACID transactions.<\/li>
      2. Support for relational modeling such that we can easily perform join operations on normalized data.<\/li><\/ol>\n\n\n\n

        When we typically step outside of relational database systems into the world of schemaless solutions, ACID transactions and relational, normalized data are often things we sacrifice. So we want to make sure that when we optimize for serverless we are not losing the features that have made Postgres such a strong contender for so long.<\/p>\n\n\n\n

        Azure\u2019s CosmosDB supports a variety of databases (both SQL and NoSQL) under the hood. CosmosDB also provides us with libraries that can work on both the client and server freeing us from an additional dependency like Hasura. We get some global distribution as well as automatic scale. However, we are still left with a lot of choices to make and are not free entirely from database management. We still have to manage our database size effectively and choose from many database options that all have their pros and cons.<\/p>\n\n\n\n

        What we really want is a fully managed solution where the operational overhead of choosing database size and the type of database can be abstracted away. In a general sense having to research many types of databases and estimate scale would be things that matter a lot less if we have all of the features we need. Fauna<\/a> is a solution where we don\u2019t have to worry about the size of the database nor do we have to select the type of database under the hood. We get the support of ACID transactions, global distribution, and no data loss without having to figure out the best underlying technology to achieve that. We also can freely access our database on the client or the server with full support for serverless functions. This allows us to flexibly create different types of applications in a variety of architectures such as JAMstack clients, serverless APIs, traditional long-running backends, or combinations of these styles.<\/p>\n\n\n\n

        When it comes to schemaless databases, we gain flexibility but are forced to think differently about our data model to most efficiently query our data. When moving away from Postgres this is often a subtle but large point of friction. With Fauna<\/a>, we have to move into a schemaless design as you cannot opt into another database type. However, Fauna makes use of a unique document-relational database model. This allows us to utilize relational database knowledge and principles when modeling our data into collections and indexes. This is why I think it\u2019s worth considering for people used to Postgres as the mental overhead is not the same as with other NoSql options.<\/p>\n\n\n

        Conclusion<\/h2>\n\n\n

        Systems like Postgres have been powerful allies for building applications for over thirty years. The rise of agile and iterative development cycles led us to the serverless revolution before us today. We are able to build increasingly more complex applications with less operational overhead than ever before. That power requires us to think about databases differently and demand a similar level of flexibility and ease of management. We want to preserve the best qualities of a Postgres, like ACID transactions, but ditch the more unsavory aspects of working with the database like connection pooling, provisioning resources, security, distribution and managing scale, availability and reliability.<\/p>\n\n\n\n

        Solutions such as Amazon\u2019s Aurora Serverless v2 create a serverless solution that works in this new world. There are also solutions like Hasura that sit on top of this to further fulfill the promise of serverless. We also have solutions like Cosmos DB and Fauna<\/a> that are not based in Postgres but are built for serverless while supporting important Postgres functionality.<\/p>\n\n\n\n

        While Cosmos DB gives us a lot of flexibility in terms of what database we use, it still leaves us with many decisions and is not completely free of operational overhead. Fauna<\/a> has made it so you don\u2019t have to compromise on ACID transactions, relational modeling or normalized data\u2009\u2014\u2009while still alleviating all the operational overhead of database management. Fauna is a complete rethinking of a database that is truly free of operational overhead. By combining the best of the past with the needs of the future Fauna has built a solution that behaves more like a data API and feels natural in a serverless future.<\/p>\n\n\n\n


        \n\n\n\n

        Follow Michael Rispoli<\/a> on Twitter<\/small><\/p>\n","protected":false},"excerpt":{"rendered":"

        Serverless architectures have brought engineering teams a great number of benefits. We get simpler deployments, automatic and infinite scale, better concurrency, and a stateless API surface. It\u2019s hard to imagine going back to the world of managed services, broken local environments, and SSHing into servers. When I started doing web development, moving from servers in […]<\/p>\n","protected":false},"author":282923,"featured_media":341186,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_bbp_topic_count":0,"_bbp_reply_count":0,"_bbp_total_topic_count":0,"_bbp_total_reply_count":0,"_bbp_voice_count":0,"_bbp_anonymous_reply_count":0,"_bbp_topic_count_hidden":0,"_bbp_reply_count_hidden":0,"_bbp_forum_subforum_count":0,"sig_custom_text":"","sig_image_type":"featured-image","sig_custom_image":0,"sig_is_disabled":false,"inline_featured_image":false,"c2c_always_allow_admin_comments":false,"footnotes":"","jetpack_publicize_message":"Rethinking Postgres in a Post-Server World with @fauna","jetpack_is_tweetstorm":false,"jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":true,"jetpack_social_options":[]},"categories":[508],"tags":[],"jetpack_publicize_connections":[],"acf":[],"jetpack_featured_media_url":"https:\/\/i0.wp.com\/css-tricks.com\/wp-content\/uploads\/2021\/05\/rethinking-postgres.png?fit=1200%2C600&ssl=1","jetpack-related-posts":[{"id":252601,"url":"https:\/\/css-tricks.com\/serverless\/","url_meta":{"origin":340910,"position":0},"title":"“Serverless”","date":"March 10, 2017","format":false,"excerpt":"I made a site all about serverless and how it relates to front-end developers. Every time I use the word \"serverless\", which is somewhat regularly lately, as we've had a few articles using the term lately and use the concept at CodePen for a variety of things, I get some\u2026","rel":"","context":"In "Article"","img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":304538,"url":"https:\/\/css-tricks.com\/the-3-laws-of-serverless\/","url_meta":{"origin":340910,"position":1},"title":"The 3 Laws of Serverless","date":"March 6, 2020","format":false,"excerpt":"Burke Holland thinks that to \"build applications without thinking about servers\" is a pretty good way to describe serverless, but... Nobody really thinks about servers when they are writing their code. I mean, I doubt any developer has ever thrown up their hands and said \u201cWhoa, whoa, whoa. Wait just\u2026","rel":"","context":"In "Link"","img":{"alt_text":"","src":"https:\/\/i0.wp.com\/css-tricks.com\/wp-content\/uploads\/2020\/03\/holland-law-furthest-abstraction.png?fit=1200%2C600&ssl=1&resize=350%2C200","width":350,"height":200},"classes":[]},{"id":273822,"url":"https:\/\/css-tricks.com\/psa-yes-serverless-still-involves-servers\/","url_meta":{"origin":340910,"position":2},"title":"PSA: Yes, Serverless Still Involves Servers.","date":"July 16, 2018","format":false,"excerpt":"You clever dog. You've rooted it out! It turns out when you build things with serverless technology you're still using servers. Pardon the patronizing tone there, I've seen one-too-many hot takes at this point where someone points this fact out and trots away triumphantly. And yes, because serverless still involves\u2026","rel":"","context":"In "Article"","img":{"alt_text":"","src":"https:\/\/i0.wp.com\/css-tricks.com\/wp-content\/uploads\/2018\/07\/serverless-not-allowed.png?fit=1200%2C600&ssl=1&resize=350%2C200","width":350,"height":200},"classes":[]},{"id":332200,"url":"https:\/\/css-tricks.com\/what-if-you-could-cut-your-hosting-costs-by-80-webiny-serverless-cms-makes-it-possible\/","url_meta":{"origin":340910,"position":3},"title":"What if you could cut your hosting costs by 80%? Webiny Serverless CMS makes it possible.","date":"January 21, 2021","format":false,"excerpt":"Are you hosting one or more websites and are using a headless CMS? Are you hosting your CMS on a virtual machine or a container, or using a SaaS solution? If so, then you're paying for the uptime, regardless if the server or service is serving requests or not. Essentially,\u2026","rel":"","context":"In "Sponsored"","img":{"alt_text":"","src":"https:\/\/i0.wp.com\/css-tricks.com\/wp-content\/uploads\/2021\/01\/webiny-image2.png?fit=1200%2C677&ssl=1&resize=350%2C200","width":350,"height":200},"classes":[]},{"id":301625,"url":"https:\/\/css-tricks.com\/in-defence-of-serverless-the-term\/","url_meta":{"origin":340910,"position":4},"title":"In Defence of \u201cServerless\u201d \u2014the term","date":"January 14, 2020","format":false,"excerpt":"Ben Ellerby: For now Serverless, to me at least, manages to do a hard job, defining the borders of a very fluid and complex space of possible solutions in which we can build next-generation architectures. It would help if there was not a framework of the same name, it would\u2026","rel":"","context":"In "Link"","img":{"alt_text":"","src":"https:\/\/i0.wp.com\/css-tricks.com\/wp-content\/uploads\/2020\/01\/defense-of-serverless.png?fit=1200%2C600&ssl=1&resize=350%2C200","width":350,"height":200},"classes":[]},{"id":271134,"url":"https:\/\/css-tricks.com\/build-nodejs-apis-using-serverless\/","url_meta":{"origin":340910,"position":5},"title":"Build Nodejs APIs Using Serverless","date":"May 17, 2018","format":false,"excerpt":"Simona Cotin did a great talk at Microsoft Build about Serverless technologies, called \"Build Node APIs Using Serverless.\" In this talk, she addresses pretty much every major gotcha that you might run into while creating Serverless infrastructure for JavaScript applications. Some of the topics included, but are not limited to:\u2026","rel":"","context":"In "Link"","img":{"alt_text":"","src":"https:\/\/i0.wp.com\/css-tricks.com\/wp-content\/uploads\/2018\/05\/microsoft-build.jpg?fit=1200%2C600&ssl=1&resize=350%2C200","width":350,"height":200},"classes":[]}],"featured_media_src_url":"https:\/\/i0.wp.com\/css-tricks.com\/wp-content\/uploads\/2021\/05\/rethinking-postgres.png?fit=1024%2C512&ssl=1","_links":{"self":[{"href":"https:\/\/css-tricks.com\/wp-json\/wp\/v2\/posts\/340910"}],"collection":[{"href":"https:\/\/css-tricks.com\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/css-tricks.com\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/css-tricks.com\/wp-json\/wp\/v2\/users\/282923"}],"replies":[{"embeddable":true,"href":"https:\/\/css-tricks.com\/wp-json\/wp\/v2\/comments?post=340910"}],"version-history":[{"count":6,"href":"https:\/\/css-tricks.com\/wp-json\/wp\/v2\/posts\/340910\/revisions"}],"predecessor-version":[{"id":341430,"href":"https:\/\/css-tricks.com\/wp-json\/wp\/v2\/posts\/340910\/revisions\/341430"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/css-tricks.com\/wp-json\/wp\/v2\/media\/341186"}],"wp:attachment":[{"href":"https:\/\/css-tricks.com\/wp-json\/wp\/v2\/media?parent=340910"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/css-tricks.com\/wp-json\/wp\/v2\/categories?post=340910"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/css-tricks.com\/wp-json\/wp\/v2\/tags?post=340910"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}