In the Digitalization Workshop—one of our interdisciplinary circles—we evaluate new technologies and methods to develop innovative solutions and test modern software approaches in a practical setting. As part of a current project, we designed a web application with a backend and database that was intended to enable not only classic CRUD operations but also complex statistical analyses in the frontend.
The Digitalization Workshop specifically relies on a greenfield environment to efficiently test new technologies and evaluate their potential for real-world application. For this project, a modern tech stack was chosen: The front end was implemented using React and Material UI (MUI), the back end was developed in Kotlin, and PostgreSQL was used as the relational database.
PostgreSQL impressed us not only with its stability and widespread adoption, but also with its ability to natively store structured data in JSON format and perform high-performance searches on it. This gives us additional flexibility, especially when dealing with evolving data models.
A key decision was to choose GraphQL over REST in order to create a flexible architecture that is easily extensible and includes a public API for third-party systems. With the "schema-first" approach, we wanted to establish a foundation for centrally managing changes to the interface and enabling automatic code generation for both the front end and back end.
In the following article, we’ll take a closer look at the advantages of GraphQL and Kotlin—particularly when compared to REST and Java—and explain how we overcame the challenges of implementing the schema-first approach.
Why Kotlin Is a Modern Alternative to Java
When implementing our application, we deliberately chose technologies that facilitate modern software development while offering a high degree of stability and scalability. We therefore chose Kotlin as the programming language for the backend—a modern, statically typed language designed specifically to meet the requirements of contemporary software development.
The language developed by JetBrains offers numerous advantages over Java without sacrificing compatibility with the existing Java ecosystem. A key advantage is null safety: Kotlin prevents many common runtime errors, such as null pointer exceptions, at compile time. In addition, Kotlin stands out for its concise and readable syntax, which is particularly beneficial when developing web applications with Spring Boot.
An Overview of Kotlin's Key Benefits:
- Compact syntax: Less boilerplate code, faster implementation
- Readability: Implicit type definitions simplify the code
- Named Arguments: The Builder pattern is often unnecessary
- Spring Boot Support: Ideal for modern web and API applications
- Java Compatibility: Existing libraries and codebases will remain usable
This combination of modernity, security, and compatibility makes Kotlin particularly well-suited for backend systems that—as in our project—require a dynamic interface structure in combination with GraphQL.
GraphQL – More Flexibility for Modern APIs
In addition to the choice of programming language, the API’s architecture also played a decisive role—particularly in terms of flexibility, maintainability, and efficiency. While REST was long considered the standard for web APIs, we deliberately chose GraphQL for this project. The query language offers a high degree of flexibility and allows the client to retrieve exactly the data that is actually needed. This not only minimizes network load but also increases the efficiency of the entire data processing workflow.
GraphQL offers several advantages over REST:
- Efficient Data Transfer: Only relevant fields are requested
- Aggregated data sources: Data from various sources can be consolidated
- A single endpoint: Centralized API structure for a wide variety of queries
- Real-time capability: Support for WebSockets and live updates
Despite its many strengths, GraphQL also presents some challenges:
- More complex server logic: Schemas and resolvers must be properly maintained
- Performance Management: Protective mechanisms against overly complex or nested queries are necessary
- Not suitable for all APIs: For simple, resource-based use cases, REST may still be more efficient
To take full advantage of GraphQL, a clean API structure is particularly important—and that's where the "schema-first" approach comes in.
Schema-First – Structured API Development with a Central Model
A "schema-first" approach means that the entire API is first defined as a GraphQL schema. This schema serves as a common foundation for all development teams and enables parallel development of the front end and back end. Especially for more complex applications, this ensures clear responsibilities, reduces coordination efforts, and results in consistent implementation.
In the world of JavaScript, there are numerous tools for automatically generating code from such a schema—for Kotlin, however, it was necessary to specifically select and combine the appropriate tools.
This approach is based on SDL (Schema Definition Language)—a declarative description language for GraphQL interfaces. In SDL, types, queries, and mutations are formally defined and subsequently serve as a common reference for code generation in both the frontend and backend. Particularly in the schema-first approach, SDL is the central starting point for a consistent API architecture.
Tool Comparison – Generators for Kotlin-Based GraphQL Projects
The following overview presents a selection of relevant code generators for Kotlin that we have evaluated in the context of our project. The selection was based on requirements for server or client code, SDL compatibility, and framework integration:
| Name | Type | Compatibility | Advantages | Disadvantages |
|---|---|---|---|---|
| Expedia Group GraphQL Kotlin Code Generation | Server/Client | Spring Boot, Ktor, Apollo Federation | Schema-first approach with SDL support; generates data classes, resolvers, and client code; full integration with Spring and Ktor | No automatic generation of complex resolvers |
| Apollo Kotlin (formerly Apollo Android) | Client | Android, Ktor, OkHttp | Real-Time Updates via Subscriptions, Caching, and Normalization | No server-side generation |
| Netflix DGS (Domain Graph Service) | Server | Spring Boot | Integrated testing tools (e.g., mocking), SDL-first with automated schema export | No client generation |
| Kobby Gradle Plugin | Client | On the client side | Generates type-safe DSLs for complex queries; customizable via schema directives | Beta Status, Less Community Support |
| graphql-java-codegen (kobylynskyi) | Server/Client | JVM (Java, Kotlin, Scala) | Supports SDL and Introspection; flexible mapping of scalars | Focus on Java; Kotlin features are limited |
| GraphQL SPQR | Server | Jump, Quarkus | Code-first approach, minimal boilerplate | No SDL-first support |
| The Guild Codegen | Client | JVM, JavaScript | Easy configuration for enums and input types, cross-platform support | Limited Functionality |
| Karate API Testing (GraphQL Support) | Testing | Test Environments | Automatic Generation of Test Code, Integrated Mocking | No production code generation |
Since there is currently no single generator that comprehensively supports both server-side and client-side code for Kotlin, it is often necessary in practice to combine several specialized tools. This allows for targeted support of specific project requirements—such as subscriptions, typed queries, or federation.
Code Generation from GraphQL to Kotlin – Potential & Challenges
The decision to adopt the schema-first approach was accompanied by a commitment to generate as much code as possible automatically. This offers significant advantages—particularly in terms of consistency and type safety—but also requires a shift in mindset within the development process.
Typical challenges:
- Schema Management: Additional Structures & Conventions Are Needed
- Error Management: Improved error messages compared to standard messages such as
INTERNAL_ERROR - Framework Compatibility: Not all libraries are fully compatible with Kotlin
A key tool for us was Expedia Group’s GraphQL Kotlin Codegen. It offers stable integration with Spring Boot and Ktor, fully supports SDL, and generates both data classes and resolvers. However, the automatic generation of complex business resolvers is still limited—manual intervention is still required in these cases.
Code generation based on a central schema provides a strong foundation for scalable, maintainable architectures—especially when used in conjunction with Kotlin. The initial extra effort required for tooling and structure pays off significantly later in the project through clear interfaces, fewer inconsistencies, and faster implementation of changes.
Conclusion – Developing Modern APIs Efficiently
The combination of Kotlin and GraphQL provides a powerful foundation for developing modern, scalable web applications. Kotlin stands out for its concise syntax, high type safety, and excellent integration into existing Java ecosystems—making it ideal for backend development.
GraphQL, in turn, opens up new possibilities for flexible API architectures and targeted data communication—especially in dynamic project contexts. The "schema-first" approach and well-designed code generation make it possible to efficiently manage technological complexity.
Our project at the IT Sonix Digitalization Workshop shows that with the right combination of new technologies, we can create software solutions that deliver high performance in the short term while remaining maintainable and scalable in the long term.