graphql-modules: a modular structure for a GraphQL server
Enterprise Grade Tooling For Your GraphQL Server
At a glance
- What is it?
- graphql-modules is a toolset of libraries and guidelines for building a GraphQL server out of reusable, testable modules, where each module owns its own schema and resolvers and the application composes them. It suits a team whose GraphQL server has outgrown a single file, and its dependency injection is the feature that makes modules testable rather than merely organised.
- Who is it for?
- Adopt graphql-modules when your GraphQL server has grown past one file and you need per-module ownership, per-module tests and shared modules across applications. Skip it if you have a small schema with one team, because the module boundary costs you ceremony that a single file does not need.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 10 days ago.
- What is it written in?
- Mainly TypeScript, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 20, 2026, and from our analysis. They are not legal advice.
Editorial analysis
Modules are defined by their schema
graphql-modules is a toolset of libraries and guidelines dedicated to creating reusable, maintainable, testable and extendable modules out of your GraphQL server. The key design decision is in the highlights list and it is worth reading twice. Modules are defined by their GraphQL schema, which the README calls a schema first design, and they can be shared between apps. That word, first, is doing real work. A module is not a directory that happens to contain some resolvers, it is a self-contained unit of the type system, and its schema is the contract. The consequence is that a module can be moved to another repository, published to an internal package registry, or shared by a second application without either side knowing much about the other, because the only thing that crosses the boundary is the type surface and the resolvers behind it. The topics list the relevant concerns, with graphql, apollo-server, apollo, dependency-injection and modules, and the primary language is TypeScript under an MIT licence.
The two-call API
The surface area is small enough to hold in your head. You create a module with `createModule`, giving it an id, its typeDefs and its resolvers, and you create an application with `createApplication`, giving it the list of modules:
import { createModule, createApplication, gql } from 'graphql-modules'
const module = createModule({
id: 'my-module',
typeDefs: gql`
type Post {
id: ID
title: String
author: User
}
type Query {
posts: [Post]
}
`,
resolvers: blogResolvers
})
const application = createApplication({
modules: [module]
})That is the whole model. A module is a schema plus resolvers, and an application is a list of modules. There is no registry, no resolver map to merge by hand, and no need to keep a single schema file in sync with a single resolver file. The `gql` tag is there so the schema is a tagged template literal in the same file as the resolvers it describes, which keeps the two adjacent rather than in parallel files that drift. The `id` matters too, since it is how the framework refers to a module when something goes wrong at runtime and when a module needs to reach another.
Gradual growth as the design goal
The third highlight is a claim about the path between two extremes. Modules offer a clear, gradual path from a very simple and fast, single-file modules setup, to scalable multi-file, multi-team, multi-repo, multi-server modules. That is the unusual framing, and it is a real design constraint rather than marketing. Most modularisation tools assume you are already large and are trying to impose a structure, and they make the small case painful. The claim here is that the same API serves a single developer with one file and a group of teams across several repositories. The second highlight is the scalable structure, managing multiple teams and features, multiple micro-services and servers, and the first is reusable modules that can be shared between apps. The third highlight is testability, described as a rich toolset around testing, mocking and separation, and the testing section is where the design pays off.
Dependency injection is what makes a module testable
The topic list includes dependency-injection, and there is a dedicated example for it in the repository. The reason injection is the load-bearing feature is that a module's resolvers usually need services, a database client, a logger, a current user, a configuration. In a single-file server those are module-level imports, which means a test has to construct the whole world before it can call a resolver. With injection, a resolver asks for what it needs and the test provides a fake. That is what makes the separation claim real rather than organisational. The repository ships two examples that show the progression, a simple GraphQL Modules example in `examples/basic` and a dependency injection example in `examples/basic-with-dependency-injection`, and the second is where the difference becomes visible. Other examples in the tree show the framework in different hosts, with `examples/apollo-subscriptions/`, `examples/subscriptions/`, `examples/graphql-yoga/` directories, which tells you the module concept is not tied to one server runtime.
Installing, and the canary you probably do not want
The install is one command:
$ npm install graphql-modulesOr with Yarn:
$ yarn add graphql-modulesThe repository root shows this is a Yarn workspaces monorepo with `packages/*` and `examples/*` as the workspace globs, and the release process runs through changesets, with a `release` script of `changeset publish` and a `pr` script of `changeset`. The pre-release story is the part to be careful about. The project publishes a pre-release version to npm on each change, and the instruction is to look at the build status on GitHub Actions and find the Publish Canary job to get the published version. A canary published on every change is useful for the maintainers and for catching a break early, and it is a bad thing to have installed by accident in production, since npm resolves a pre-release tag differently depending on the range you write. Pin an explicit version if you care about reproducibility.
Where the framework stops, and what you keep building
graphql-modules is a structuring tool, and the boundary is worth stating because the name suggests more. It does not run a server, and it does not replace Apollo Server or GraphQL Yoga, since the examples show the modules being used with those hosts. It does not generate types, and it does not give you a client. What it gives you is a way to partition a schema, an application composition step and a testing and mocking toolset. The cost is the convention. Every module has an id, its schema has to be written in a way that composes, and shared types have to live somewhere both modules can reach, which is a genuine design decision each time rather than an automatic consequence. The repository root also shows the practical surface of maintaining it, with a `website/` directory, a `benchmark/` directory with a `benchmark:basic` script, a `.changeset/` directory, `bob.config.js` for the build, `jest.config.js` and `jest.config.base.js` for the tests, `renovate.json` for dependency updates and a `.husky/` directory with a `prepare` script that runs `husky install`.
Editorial conclusion
Adopt graphql-modules when your GraphQL server has grown past one file and you need per-module ownership, per-module tests and shared modules across applications. Skip it if you have a small schema with one team, because the module boundary costs you ceremony that a single file does not need. Before you migrate, plan the module boundary by schema rather than by folder, since the design is schema first, and note that the project publishes a canary build on every change, so pin a stable version rather than tracking the latest tag if you want reproducible installs.
Frequently asked questions
What is graphql-modules?
A toolset of libraries and guidelines for creating reusable, maintainable, testable and extendable modules out of a GraphQL server. Modules are defined by their GraphQL schema in a schema first design and can be shared between apps, and the application is composed from a list of modules.
How do I install graphql-modules?
Run `npm install graphql-modules` or `yarn add graphql-modules`. The package also publishes a pre-release canary to npm on each change, and you can find the published version by looking at the Publish Canary job on GitHub Actions.
How do I create a module and an application?
Call createModule with an id, typeDefs written with the gql tag and your resolvers, then call createApplication with a modules array. The README shows a basic module with a Post type and a posts query, and there are examples for both the basic case and dependency injection.
Is graphql-modules tied to Apollo Server?
No. The examples directory includes projects using Apollo subscriptions, subscriptions, GraphQL Yoga and a basic dependency injection example, so the module concept is not tied to one server runtime.
What licence is graphql-modules released under?
MIT. The package manifest for the monorepo root sets the licence to MIT and the README carries the MIT badge and statement.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/graphql-hive-graphql-modules)Was this useful?