DEV Community

Moya Richards
Moya Richards

Posted on

Split your AWS AppSync schema across multiple files

If you’re working with AWS AppSync or any modular GraphQL API, you’ve probably want to split your schema across multiple files. This is great for developer sanity—but AppSync prefers a single .graphql file.

Let’s automate that.

This post walks through a simple Node.js script that uses the @graphql-tools ecosystem to:

✅ Load and merge your GraphQL schemas
✅ Resolve conflicts
✅ Write the final result to a single .graphql file
✅ load schema into your AppSync deployment flow


🛠 Setup

Install the necessary dependencies:

npm install @graphql-tools/load-files @graphql-tools/merge graphql
Enter fullscreen mode Exit fullscreen mode

📦 Your Project Structure

Assume your project is organized like this:

project-root/
├── appsync/
│   ├── mutations/
│   │   └── addCustomer.graphql
│   ├── queries/
│   │   └── getCustomer.graphql
│   └── schema_chatbot_quicksight_merged.graphql (output)
├── mergeSchemas.js
Enter fullscreen mode Exit fullscreen mode

🧩 The Merge Script

Here’s the full script to merge your GraphQL schema files:

import { loadFilesSync } from "@graphql-tools/load-files";
import { mergeTypeDefs } from "@graphql-tools/merge";
import { print } from "graphql";
import fs from "fs";
import path from "path";
import { fileURLToPath } from "url";

try {
    const __filename = fileURLToPath(import.meta.url);
    const __dirname = path.dirname(__filename);
    const mergedFileName = "schema_chatbot_quicksight_merged.graphql";
    const outputPath = path.join(__dirname, "./appsync", mergedFileName);

    const typesArray = loadFilesSync(path.join(__dirname, "./appsync/**/*.graphql"), {
        extensions: [".graphql"],
        ignore: [mergedFileName],
    });

    if (!typesArray || typesArray.length === 0) {
        throw new Error("No GraphQL schema files found");
    }

    console.log(
        "Loaded files:",
        typesArray.map((t) => t?.loc?.source?.name || typeof t),
    );

    const mergedTypeDefs = mergeTypeDefs(typesArray, {
        all: true,
        throwOnConflict: true,
    });

    const sdl = print(mergedTypeDefs);

    const outputDir = path.dirname(outputPath);
    if (!fs.existsSync(outputDir)) {
        fs.mkdirSync(outputDir, { recursive: true });
    }

    fs.writeFileSync(outputPath, sdl);
    console.log(`✅ Merged schema written to appsync/${mergedFileName}`);
} catch (error) {
    console.error("❌ Error merging GraphQL schemas:", error.message);
    process.exit(1);
}
Enter fullscreen mode Exit fullscreen mode

🚀 Using It in AWS CDK

Once your merged schema is generated, you can use it directly in your CDK stack with aws-cdk-lib/aws-appsync.

Here’s an example:

import * as cdk from "aws-cdk-lib";
import { Construct } from "constructs";
import * as appsync from "aws-cdk-lib/aws-appsync";
import * as path from "path";

export class AppsyncStack extends cdk.Stack {
  constructor(scope: Construct, id: string, props?: cdk.StackProps) {
    super(scope, id, props);

    const api = new appsync.GraphqlApi(this, "graphql-api", {
      name: "ChatbotQuickSightApi",
      schema: appsync.SchemaFile.fromAsset(
        path.join(__dirname, "../appsync/schema_chatbot_quicksight_merged.graphql")
      ),
      authorizationConfig: {
        defaultAuthorization: {
          authorizationType: appsync.AuthorizationType.API_KEY,
        },
      },
      xrayEnabled: true,
    });

    new cdk.CfnOutput(this, "GraphQLAPIURL", {
      value: api.graphqlUrl,
    });
  }
}
Enter fullscreen mode Exit fullscreen mode

🧠 Tip

You can run your mergeSchemas.js script as part of your CDK build pipeline. For example:

"scripts": {
  "prepare-schema": "node mergeSchemas.js",
  "build": "npm run prepare-schema && cdk synth"
}
Enter fullscreen mode Exit fullscreen mode

🧼 Why This Matters

  • Keep your schema modular for readability and reuse
  • Deliver a single file AppSync expects without error-prone copy/paste
  • Enable CI/CD integration with schema validation and bundling in one step

Top comments (0)