{"id":5590,"date":"2017-10-14T17:13:16","date_gmt":"2017-10-14T17:13:16","guid":{"rendered":"https:\/\/cheesecakelabs.com\/blog\/?p=5590\/"},"modified":"2022-07-01T17:29:45","modified_gmt":"2022-07-01T17:29:45","slug":"case-clojure-graphql-replacing-django","status":"publish","type":"post","link":"https:\/\/cheesecakelabs.com\/blog\/case-clojure-graphql-replacing-django\/","title":{"rendered":"The Case for Clojure and GraphQL: Replacing Django"},"content":{"rendered":"<p style=\"text-align: left;\">In the last few months, I worked on two projects that were similar in scope and complexity; both were API backends for mobile apps, had similar requirements and timeframes. However, one thing set them apart: one was written in <a href=\"https:\/\/cheesecakelabs.com\/blog\/blog\/django-framework-app-development\/\">Django<\/a> + REST while the other was written in Clojure + GraphQL.<\/p>\n<p>Since I was the main developer for both projects, I was able to make useful comparisons between both approaches. In this post, I\u2019ll describe the pros and cons of each.<\/p>\n<p><!--more--><\/p>\n<h2><a id=\"The_Good_Parts_4\"><\/a>The Good Parts<\/h2>\n<h3><a id=\"Clojure_6\"><\/a>Clojure<\/h3>\n<p>I won\u2019t get into details about why Clojure is awesome since there are&nbsp;<a href=\"http:\/\/owenrh.me.uk\/blog\/2015\/08\/24\/\">many blogs<\/a>&nbsp;around the web that do a&nbsp;<a href=\"http:\/\/blog.venanti.us\/why-clojure\/\">much<\/a>&nbsp;<a href=\"https:\/\/eli.thegreenplace.net\/2017\/clojure-the-perfect-language-to-expand-your-brain\/\">better job<\/a>&nbsp;than me, but I\u2019ll say this: the combination of immutability,&nbsp;<a href=\"https:\/\/vvvvalvalval.github.io\/posts\/what-makes-a-good-repl.html\">repl-driven<\/a>&nbsp;development, and functional programming is unmatched in any other language in terms of a productive and fun <a href=\"https:\/\/cheesecakelabs.com\/blog\/blog\/building-app-phase-3-product-development\/\">development<\/a> experience.<\/p>\n<h3><a id=\"Lacinia_9\"><\/a>Lacinia<\/h3>\n<p>There are a few GraphQL options in Clojure and, after testing the popular libraries, one came out way ahead of the others:&nbsp;<a href=\"https:\/\/medium.com\/walmartlabs\/open-sourcing-lacinia-our-graphql-library-for-clojure-96a4ce5fc7b8\">Lacinia<\/a>. It follows the Clojure principles of simplicity and data over functions over macros, letting the developer compose the schema in pure(ish) EDN. It is also used for internal APIs at Walmart.<\/p>\n<p><img decoding=\"async\" class=\"aligncenter size-full wp-image-5608\" src=\"https:\/\/ckl-website-static.s3.amazonaws.com\/wp-content\/uploads\/2017\/10\/Lacinia.jpg\" alt=\"\" width=\"1684\" height=\"776\" srcset=\"https:\/\/ckl-website-static.s3.amazonaws.com\/wp-content\/uploads\/2017\/10\/Lacinia.jpg 1684w, https:\/\/ckl-website-static.s3.amazonaws.com\/wp-content\/uploads\/2017\/10\/Lacinia-768x354.jpg 768w\" sizes=\"(max-width: 1684px) 100vw, 1684px\" \/><\/p>\n<p>Now, this is one well-designed library. It is simple, predictable, makes extending the code base a breeze and gets out of the way when things get complex. When you need to add a new query or mutation (GraphQL parlance for endpoints), it is simply a matter of updating the schema, writing the resolver function (which is datastore-agnostic, so you can fetch from one or multiple stores or even a REST endpoint) and you\u2019re done. Plus, the error messages are excellent (especially for a Clojure lib).<\/p>\n<p>There aren\u2019t many resources around to lean Lacinia, but the&nbsp;<a href=\"http:\/\/lacinia.readthedocs.io\/en\/latest\/\">docs<\/a>&nbsp;are decent, there\u2019s&nbsp;<a href=\"https:\/\/jborden.github.io\/2017\/05\/15\/using-lacinia\">a nice tutorial<\/a>&nbsp;and an&nbsp;<a href=\"https:\/\/www.youtube.com\/watch?v=I0vVkQfmy9w\">excellent talk<\/a>&nbsp;to get things started.<\/p>\n<h3><a id=\"Less_Friction_Between_Mobile_and_Backend_Teams_17\"><\/a>Less Friction Between Mobile and Backend Teams<\/h3>\n<p>Compared to the Django project, we experienced a lot less friction between the backend and mobile teams. There were fewer arguments about which fields an endpoint should provide or how to format a response since the client can just query however it wants.<\/p>\n<p>In addition, having a typed schema means there\u2019s a contract sitting between the client and the data that guarantees the entire team is on the same page from the start. It makes it possible to introspect the schema, which is used to great advantage in the GraphQL world.<\/p>\n<p>Once the schema is defined, anyone with the&nbsp;<a href=\"https:\/\/github.com\/graphql\/graphiql\">GraphiQL<\/a>&nbsp;client can interactively explore it with niceties such as autocompletion, syntax highlighting and even pretty formatting. This alone is worth its weight in gold. I am a fan of auto-generated API docs, and this feature makes the project less likely to suffer from documentation drift.<\/p>\n<p>Since GraphQL queries are extremely flexible, allowing the client to rename fields in the response and even fetch the entire UI\u2019s requirements in one go,&nbsp;<strong>the need for UI-aware endpoints is retired<\/strong>.<\/p>\n<h3><a id=\"Less_Bugs_27\"><\/a>Fewer Bugs<\/h3>\n<p>Every commit we make is formatted according to the&nbsp;<a href=\"https:\/\/github.com\/angular\/angular.js\/blob\/master\/CONTRIBUTING.md#commit\">Angular git commit guidelines<\/a> so that we can auto-generate nice changelogs. This also allowed us to generate a few stats for comparison: <strong>the Django codebase contains 0.8 fixes for every feature committed while the Clojure codebase contains 0.2 fixes for every feature<\/strong>. This is a huge difference and, to be honest, I can\u2019t really attribute this to either Clojure, Lacinia or GraphQL alone, but I think the synergy between these technologies is powerful.<\/p>\n<p><img decoding=\"async\" class=\"aligncenter size-full wp-image-5615\" src=\"https:\/\/ckl-website-static.s3.amazonaws.com\/wp-content\/uploads\/2017\/10\/f1.jpg\" alt=\"\" width=\"720\" height=\"494\"><\/p>\n<h3><a id=\"Less_Lines_of_Code_30\"><\/a>Fewer Lines of Code<\/h3>\n<p>This might be related to the point above since it\u2019s known that&nbsp;<a href=\"https:\/\/cacm.acm.org\/magazines\/2017\/10\/221326-a-large-scale-study-of-programming-languages-and-code-quality-in-github\/fulltext\">there\u2019s a correlation<\/a>&nbsp;between the LOC and the number of bugs in a codebase.<\/p>\n<blockquote><p>I happen to hold a hard-won minority opinion about code bases. In particular I believe, quite staunchly I might add, that the worst thing that can happen to a code base is size.<br \/>\n\u2013 Steve Yegge<\/p><\/blockquote>\n<p>Even though we had to implement many features that come for free with Django (or Django Rest Framework) in the Clojure project, like an admin site, token-based authentication, and social authentication, in the end, there were fewer lines of code. As of this writing, the Clojure project contains&nbsp;<strong>~53% fewer lines of code<\/strong>.<\/p>\n<h2><a id=\"The_Bad_Parts_38\"><\/a>The Bad Parts<\/h2>\n<h3><a id=\"Immature_Ecosystem_40\"><\/a>Immature Ecosystem<\/h3>\n<p>In Django-land, most of the features that you might need in a web app are covered by an external library. Authentication is a good example: there are many mature libraries that are mostly plug and play, which lets you focus on the important part of the problem domain. Although there are lots of web libraries for Clojure, the number of libraries that solve the authentication problem for GraphQL is zero: you have to write your own. It is not a big deal since there are excellent libraries like Buddy to help you along but still, not even close to plug and play.<\/p>\n<p>Besides libraries, there\u2019s also the problem that there\u2019s no consensus on many architecture issues, like: status codes, auth, and file uploads.<\/p>\n<p>GraphQL endpoints always return 200 so there\u2019s no status code to convey what happened in case of an error because it doesn\u2019t surface errors from the backend. Of course, HTTP error codes have nothing to do with the failure of a GraphQL query, where a field resolver might return an error but the parent did not. Still, these are open questions and left to the developer to figure out.<\/p>\n<p>We chose to be pragmatic from the start so, given a roadblock, we would implement the endpoint as REST and, later, try to find an idiomatic GraphQL solution. We hit this situation twice right at the beginning with authentication and file uploads and, months later, we still haven\u2019t found a solution for file uploads.<\/p>\n<p>We tried using base64 string-based mutations for file uploads, but there were two very problematic downsides: base64 makes files sizes ~30% larger and you lose the option of restarting a failed upload.<\/p>\n<h3><a id=\"Overfetching_51\"><\/a>Over-fetching<\/h3>\n<p>GraphQL doesn\u2019t care about your store(s), it only cares about calling your resolve methods for populating the data for the request, so it is&nbsp;<em>very easy to run into n+1&nbsp;queries<\/em>* and performance issues. Granted, even with those problems, an unoptimized Clojure app is an order of magnitude faster than a fast Django server). However, the burden is entirely on the developer to build smart resolvers<\/p>\n<h3><a id=\"Luminus_Support_54\"><\/a>Luminus Support<\/h3>\n<p>Our main tool for writing web servers in Clojure is <a href=\"http:\/\/www.luminusweb.net\/\">Luminus<\/a>, an awesome set of tested and documented utilities and libraries to start you off. Lacinia provides a companion library that exposes your schema as Pedestal endpoints and has support for subscriptions and a few utilities, but none for Luminus (we\u2019re working on something).<\/p>\n<h3><a id=\"No_Admin_57\"><\/a>No Admin<\/h3>\n<p>Django provides out of the box a pretty decent admin interface, which is in itself a strong reason for choosing Django. There is no corresponding package for Clojure so our only choice was to develop a custom admin interface. Fortunately, we found a great library called&nbsp;<a href=\"https:\/\/marmelab.com\/admin-on-rest\">Admin on Rest<\/a>, which lets you build a custom admin interface using pre-built React components.<\/p>\n<h3><a id=\"Small_Stuff_60\"><\/a>Small Stuff<\/h3>\n<p>I left these for last because these complaints are not new in the Clojure community: horrendous Java stack traces, memory usage and startup time still suck. Plus, there\u2019s the impedance mismatch between JS\u2019s camel case and Clojure\u2019s kebab case.<\/p>\n<h3><a id=\"Considerations_63\"><\/a>Considerations<\/h3>\n<p>Generally, it was a much better experience developing a web app in Clojure + GraphQL than Django + Django Rest Framework. I feel like my experience is comparable in both languages (I\u2019ve been using Clojure since 2009 and Python since 2007) and, although these were different projects, there were a lot of similarities in scope and size.<\/p>\n<p>Besides being a framework on top of another framework, which makes it hard for a developer not familiar with DRF\u2019s idioms to extend the codebase, the Django + DRF combo tends to encourage complex OO code, where you have to know exactly which methods to override when you need custom functionality, making the code path from an endpoint to the actual data fetching kind of opaque. If you only know <a href=\"https:\/\/cheesecakelabs.com\/blog\/blog\/biggest-benefits-of-python\/\">Python<\/a>, then the learning curve is pretty steep.<\/p>\n<blockquote><p>\u2026 the real win with choosing a immutable functional language such as Clojure is around the 2\/3 mark in a project. Just when a large traditional OO system starts to buckle under it\u2019s own gravity \u2026 this is when a Clojure code-base will shine in comparison<br \/>\n<a href=\"http:\/\/www.pitheringabout.com\/?p=1069\">Jon Pither<\/a><\/p><\/blockquote>\n<p>Clojure + Lacinia is the opposite to the above problem: everything\u2019s just plain Clojure, using the same data structures you\u2019re used to. If you know the language well, it\u2019ll only take a few hours to get going.<\/p>\n<p>In the end, although there\u2019s a very large ecosystem around web development in Python and Django comes by default with the inimitable admin, given a similar project (backend API for a mobile app) I would choose Clojure (and probably Lacinia) for the simplicity and productivity.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>In the last few months, I worked on two projects that were similar in scope and complexity; both were API backends for mobile apps, had similar requirements and timeframes. However, one thing set them apart: one was written in Django + REST while the other was written in Clojure + GraphQL. Since I was the [&hellip;]<\/p>\n","protected":false},"author":65,"featured_media":5601,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[432],"tags":[350],"class_list":["post-5590","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-engineering","tag-tag-django"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.1.1 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>The Case for Clojure and GraphQL: Replacing Django<\/title>\n<meta name=\"description\" content=\"There are a few GraphQL options in Clojure and, after testing the popular libraries, one came out way ahead of the others: Lacinia.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/cheesecakelabs.com\/blog\/case-clojure-graphql-replacing-django\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"The Case for Clojure and GraphQL: Replacing Django\" \/>\n<meta property=\"og:description\" content=\"There are a few GraphQL options in Clojure and, after testing the popular libraries, one came out way ahead of the others: Lacinia.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/cheesecakelabs.com\/blog\/case-clojure-graphql-replacing-django\/\" \/>\n<meta property=\"og:site_name\" content=\"Cheesecake Labs\" \/>\n<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/cheesecakelabs\" \/>\n<meta property=\"article:published_time\" content=\"2017-10-14T17:13:16+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2022-07-01T17:29:45+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/ckl-website-static.s3.amazonaws.com\/wp-content\/uploads\/2017\/10\/django_banner.png\" \/>\n\t<meta property=\"og:image:width\" content=\"2000\" \/>\n\t<meta property=\"og:image:height\" content=\"720\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"author\" content=\"Cheesecake Labs\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@cheesecakelabs\" \/>\n<meta name=\"twitter:site\" content=\"@cheesecakelabs\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"9 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/cheesecakelabs.com\/blog\/case-clojure-graphql-replacing-django\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/cheesecakelabs.com\/blog\/case-clojure-graphql-replacing-django\/\"},\"author\":{\"name\":\"Rodrigo Landerdahl\"},\"headline\":\"The Case for Clojure and GraphQL: Replacing Django\",\"datePublished\":\"2017-10-14T17:13:16+00:00\",\"dateModified\":\"2022-07-01T17:29:45+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/cheesecakelabs.com\/blog\/case-clojure-graphql-replacing-django\/\"},\"wordCount\":1512,\"commentCount\":0,\"image\":{\"@id\":\"https:\/\/cheesecakelabs.com\/blog\/case-clojure-graphql-replacing-django\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/ckl-website-static.s3.amazonaws.com\/wp-content\/uploads\/2017\/10\/django_banner.png\",\"keywords\":[\"Django\"],\"articleSection\":[\"Engineering\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/cheesecakelabs.com\/blog\/case-clojure-graphql-replacing-django\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/cheesecakelabs.com\/blog\/case-clojure-graphql-replacing-django\/\",\"url\":\"https:\/\/cheesecakelabs.com\/blog\/case-clojure-graphql-replacing-django\/\",\"name\":\"The Case for Clojure and GraphQL: Replacing Django\",\"isPartOf\":{\"@id\":\"https:\/\/cheesecakelabs.com\/blog\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/cheesecakelabs.com\/blog\/case-clojure-graphql-replacing-django\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/cheesecakelabs.com\/blog\/case-clojure-graphql-replacing-django\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/ckl-website-static.s3.amazonaws.com\/wp-content\/uploads\/2017\/10\/django_banner.png\",\"datePublished\":\"2017-10-14T17:13:16+00:00\",\"dateModified\":\"2022-07-01T17:29:45+00:00\",\"author\":{\"@type\":\"person\",\"name\":\"Rodrigo Landerdahl\"},\"description\":\"There are a few GraphQL options in Clojure and, after testing the popular libraries, one came out way ahead of the others: Lacinia.\",\"breadcrumb\":{\"@id\":\"https:\/\/cheesecakelabs.com\/blog\/case-clojure-graphql-replacing-django\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/cheesecakelabs.com\/blog\/case-clojure-graphql-replacing-django\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/cheesecakelabs.com\/blog\/case-clojure-graphql-replacing-django\/#primaryimage\",\"url\":\"https:\/\/ckl-website-static.s3.amazonaws.com\/wp-content\/uploads\/2017\/10\/django_banner.png\",\"contentUrl\":\"https:\/\/ckl-website-static.s3.amazonaws.com\/wp-content\/uploads\/2017\/10\/django_banner.png\",\"width\":2000,\"height\":720,\"caption\":\"Clojure\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/cheesecakelabs.com\/blog\/case-clojure-graphql-replacing-django\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/cheesecakelabs.com\/blog\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"The Case for Clojure and GraphQL: Replacing Django\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/cheesecakelabs.com\/blog\/#website\",\"url\":\"https:\/\/cheesecakelabs.com\/blog\/\",\"name\":\"Cheesecake Labs\",\"description\":\"Nearshore outsourcing company for Web and Mobile design and engineering services, and staff augmentation for startups and enterprises..\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/cheesecakelabs.com\/blog\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Person\",\"name\":\"Rodrigo Landerdahl\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/cheesecakelabs.com\/blog\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/ckl-website-static.s3.amazonaws.com\/wp-content\/uploads\/2017\/05\/rodrigo-300x300.jpg\",\"contentUrl\":\"https:\/\/ckl-website-static.s3.amazonaws.com\/wp-content\/uploads\/2017\/05\/rodrigo-300x300.jpg\",\"caption\":\"Rodrigo Landerdahl\"},\"description\":\"10 years of experience in Marketing and Sales in the Technology sector. My main purpose is help, support and structure efficient operations and also develop independent and multidisciplinary teams.\",\"url\":\"https:\/\/cheesecakelabs.com\/blog\/autor\/rlander\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"The Case for Clojure and GraphQL: Replacing Django","description":"There are a few GraphQL options in Clojure and, after testing the popular libraries, one came out way ahead of the others: Lacinia.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/cheesecakelabs.com\/blog\/case-clojure-graphql-replacing-django\/","og_locale":"en_US","og_type":"article","og_title":"The Case for Clojure and GraphQL: Replacing Django","og_description":"There are a few GraphQL options in Clojure and, after testing the popular libraries, one came out way ahead of the others: Lacinia.","og_url":"https:\/\/cheesecakelabs.com\/blog\/case-clojure-graphql-replacing-django\/","og_site_name":"Cheesecake Labs","article_publisher":"https:\/\/www.facebook.com\/cheesecakelabs","article_published_time":"2017-10-14T17:13:16+00:00","article_modified_time":"2022-07-01T17:29:45+00:00","og_image":[{"width":2000,"height":720,"url":"https:\/\/ckl-website-static.s3.amazonaws.com\/wp-content\/uploads\/2017\/10\/django_banner.png","type":"image\/png"}],"author":"Cheesecake Labs","twitter_card":"summary_large_image","twitter_creator":"@cheesecakelabs","twitter_site":"@cheesecakelabs","twitter_misc":{"Written by":null,"Est. reading time":"9 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/cheesecakelabs.com\/blog\/case-clojure-graphql-replacing-django\/#article","isPartOf":{"@id":"https:\/\/cheesecakelabs.com\/blog\/case-clojure-graphql-replacing-django\/"},"author":{"name":"Rodrigo Landerdahl"},"headline":"The Case for Clojure and GraphQL: Replacing Django","datePublished":"2017-10-14T17:13:16+00:00","dateModified":"2022-07-01T17:29:45+00:00","mainEntityOfPage":{"@id":"https:\/\/cheesecakelabs.com\/blog\/case-clojure-graphql-replacing-django\/"},"wordCount":1512,"commentCount":0,"image":{"@id":"https:\/\/cheesecakelabs.com\/blog\/case-clojure-graphql-replacing-django\/#primaryimage"},"thumbnailUrl":"https:\/\/ckl-website-static.s3.amazonaws.com\/wp-content\/uploads\/2017\/10\/django_banner.png","keywords":["Django"],"articleSection":["Engineering"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/cheesecakelabs.com\/blog\/case-clojure-graphql-replacing-django\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/cheesecakelabs.com\/blog\/case-clojure-graphql-replacing-django\/","url":"https:\/\/cheesecakelabs.com\/blog\/case-clojure-graphql-replacing-django\/","name":"The Case for Clojure and GraphQL: Replacing Django","isPartOf":{"@id":"https:\/\/cheesecakelabs.com\/blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/cheesecakelabs.com\/blog\/case-clojure-graphql-replacing-django\/#primaryimage"},"image":{"@id":"https:\/\/cheesecakelabs.com\/blog\/case-clojure-graphql-replacing-django\/#primaryimage"},"thumbnailUrl":"https:\/\/ckl-website-static.s3.amazonaws.com\/wp-content\/uploads\/2017\/10\/django_banner.png","datePublished":"2017-10-14T17:13:16+00:00","dateModified":"2022-07-01T17:29:45+00:00","author":{"@type":"person","name":"Rodrigo Landerdahl"},"description":"There are a few GraphQL options in Clojure and, after testing the popular libraries, one came out way ahead of the others: Lacinia.","breadcrumb":{"@id":"https:\/\/cheesecakelabs.com\/blog\/case-clojure-graphql-replacing-django\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/cheesecakelabs.com\/blog\/case-clojure-graphql-replacing-django\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/cheesecakelabs.com\/blog\/case-clojure-graphql-replacing-django\/#primaryimage","url":"https:\/\/ckl-website-static.s3.amazonaws.com\/wp-content\/uploads\/2017\/10\/django_banner.png","contentUrl":"https:\/\/ckl-website-static.s3.amazonaws.com\/wp-content\/uploads\/2017\/10\/django_banner.png","width":2000,"height":720,"caption":"Clojure"},{"@type":"BreadcrumbList","@id":"https:\/\/cheesecakelabs.com\/blog\/case-clojure-graphql-replacing-django\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/cheesecakelabs.com\/blog\/"},{"@type":"ListItem","position":2,"name":"The Case for Clojure and GraphQL: Replacing Django"}]},{"@type":"WebSite","@id":"https:\/\/cheesecakelabs.com\/blog\/#website","url":"https:\/\/cheesecakelabs.com\/blog\/","name":"Cheesecake Labs","description":"Nearshore outsourcing company for Web and Mobile design and engineering services, and staff augmentation for startups and enterprises..","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/cheesecakelabs.com\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Person","name":"Rodrigo Landerdahl","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/cheesecakelabs.com\/blog\/#\/schema\/person\/image\/","url":"https:\/\/ckl-website-static.s3.amazonaws.com\/wp-content\/uploads\/2017\/05\/rodrigo-300x300.jpg","contentUrl":"https:\/\/ckl-website-static.s3.amazonaws.com\/wp-content\/uploads\/2017\/05\/rodrigo-300x300.jpg","caption":"Rodrigo Landerdahl"},"description":"10 years of experience in Marketing and Sales in the Technology sector. My main purpose is help, support and structure efficient operations and also develop independent and multidisciplinary teams.","url":"https:\/\/cheesecakelabs.com\/blog\/autor\/rlander\/"}]}},"_links":{"self":[{"href":"https:\/\/cheesecakelabs.com\/blog\/wp-json\/wp\/v2\/posts\/5590","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/cheesecakelabs.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/cheesecakelabs.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/cheesecakelabs.com\/blog\/wp-json\/wp\/v2\/users\/65"}],"replies":[{"embeddable":true,"href":"https:\/\/cheesecakelabs.com\/blog\/wp-json\/wp\/v2\/comments?post=5590"}],"version-history":[{"count":1,"href":"https:\/\/cheesecakelabs.com\/blog\/wp-json\/wp\/v2\/posts\/5590\/revisions"}],"predecessor-version":[{"id":10259,"href":"https:\/\/cheesecakelabs.com\/blog\/wp-json\/wp\/v2\/posts\/5590\/revisions\/10259"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/cheesecakelabs.com\/blog\/wp-json\/wp\/v2\/media\/5601"}],"wp:attachment":[{"href":"https:\/\/cheesecakelabs.com\/blog\/wp-json\/wp\/v2\/media?parent=5590"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/cheesecakelabs.com\/blog\/wp-json\/wp\/v2\/categories?post=5590"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/cheesecakelabs.com\/blog\/wp-json\/wp\/v2\/tags?post=5590"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}