Clojure + GraphQL Integration

Table of Contents

Overview

Lacinia is the premier GraphQL implementation for Clojure, developed by Walmart Labs and released as open source. It provides a complete, specification-compliant GraphQL server that leverages Clojure's strengths in data transformation and functional programming. Lacinia represents GraphQL schemas as EDN data structures and resolvers as pure functions, making it idiomatic for Clojure developers building API layers.

Background

GraphQL emerged from Facebook in 2015 as an alternative to REST APIs, offering clients the ability to request exactly the data they need. For Clojure applications, Lacinia (named after a species of lacewing) became the de facto standard, first released in 2017. The library integrates naturally with Ring-based web servers and supports both synchronous and asynchronous execution models through core.async and manifold.

Key Concepts

Schema Definition

Lacinia schemas are defined as EDN maps describing types, queries, mutations, and subscriptions:

{:objects
 {:User
  {:fields {:id {:type ID}
            :name {:type String}
            :email {:type String}}}}
 :queries
 {:user {:type :User
         :args {:id {:type ID}}
         :resolve :resolve-user}}}

Resolvers

Field resolvers are functions that receive context, arguments, and the parent value:

(defn resolve-user [context args value]
  (let [{:keys [id]} args]
    (db/find-user-by-id id)))

Async Execution

Lacinia supports asynchronous resolvers using resolve-promise for non-blocking database queries and external API calls.

Pedestal Integration

lacinia-pedestal provides HTTP transport with features like GraphiQL playground, subscription support via WebSockets, and request tracing.

Implementation

Project Setup

;; deps.edn
{:deps {com.walmartlabs/lacinia {:mvn/version "1.2"}
        com.walmartlabs/lacinia-pedestal {:mvn/version "1.2"}}}

Schema Compilation

(require '[com.walmartlabs.lacinia.schema :as schema])
(require '[com.walmartlabs.lacinia.util :as util])

(def compiled-schema
  (-> schema-edn
      (util/inject-resolvers {:resolve-user resolve-user})
      schema/compile))

Query Execution

(require '[com.walmartlabs.lacinia :as lacinia])

(lacinia/execute compiled-schema
                 "{ user(id: \"123\") { name email } }"
                 nil nil)

References

Notes

  • Lacinia enforces schema-first design, encouraging API contracts before implementation
  • The library handles GraphQL introspection queries automatically
  • Consider using lacinia-gen for property-based testing of resolvers
  • For production, implement DataLoader patterns to avoid N+1 query problems

Author: Jason Walsh

j@wal.sh

Last Updated: 2026-01-11 11:00:20

build: 2026-01-11 18:38 | sha: eb805a8