X-GraphQL Migration Guide
Upgrading to x-graphql v2.0 - Breaking Changes, Migration Paths, and Automated Tools
Version: 2.0.0
Last Updated: January 2025
Table of Contents
- Overview
- Breaking Changes
- Migration Paths
- Automated Migration
- Manual Migration
- Validation
- Troubleshooting
Overview
X-GraphQL v2.0 introduces a standardized namespace structure and naming conventions. This guide helps you migrate from:
- v1.x x-graphql attributes (various naming patterns)
- legacy schemas (legacy attribute names)
- Other JSON Schema → GraphQL tools
What’s New in v2.0
✅ Consistent Naming: All attributes follow x-graphql-{category}-{name} pattern
✅ Federation Namespace: Federation attributes now prefixed x-graphql-federation-*
✅ P0 Features: Core features like skip, nullable, description fully supported
✅ Better Validation: Comprehensive schema validation and linting
✅ Migration Tools: Automated scripts for most changes
Migration Timeline
- Phase 1 (Week 1): Run migration script, update schemas
- Phase 2 (Week 2): Test converted schemas, fix manual cases
- Phase 3 (Week 3): Deploy and validate in production
- Phase 4 (Week 4): Remove deprecated v1.x support
Breaking Changes
1. Naming Convention Changes
| v1.x Attribute | v2.0 Attribute | Status |
|---|---|---|
x-graphql-scalars | x-graphql-scalar | ⚠️ Renamed |
x-graphql-shareable | x-graphql-federation-shareable | ⚠️ Moved to federation namespace |
x-graphql-keys | x-graphql-federation-keys | ⚠️ Moved to federation namespace |
x-graphql-requires | x-graphql-federation-requires | ⚠️ Moved to federation namespace |
x-graphql-provides | x-graphql-federation-provides | ⚠️ Moved to federation namespace |
x-graphql-external | x-graphql-federation-external | ⚠️ Moved to federation namespace |
x-graphql-override-from | x-graphql-federation-override-from | ⚠️ Moved to federation namespace |
x-graphql-type (string) | x-graphql-type-name | ⚠️ Renamed for clarity |
x-graphql-type (object) | x-graphql-type-name + x-graphql-type-kind | ⚠️ Split into two attributes |
2. Federation Namespace Consolidation
Before (v1.x):
{
"type": "object",
"x-graphql-type-name": "Product",
"x-graphql-keys": ["id"],
"x-graphql-shareable": true,
"properties": {
"inventory": {
"type": "integer",
"x-graphql-external": true
}
}
}After (v2.0):
{
"type": "object",
"x-graphql-type-name": "Product",
"x-graphql-federation-keys": ["id"],
"x-graphql-federation-shareable": true,
"properties": {
"inventory": {
"type": "integer",
"x-graphql-federation-external": true
}
}
}3. Description Handling
Before (v1.x) - Description always used from JSON Schema:
{
"type": "object",
"description": "This is used in both JSON Schema validation and GraphQL"
}After (v2.0) - Separate GraphQL-specific descriptions:
{
"type": "object",
"description": "Internal JSON Schema documentation",
"x-graphql-description": "Public GraphQL API documentation"
}Note: If x-graphql-description is not present, description is still used (backward compatible).
4. Type Attribute Split
Before (v1.x):
{
"x-graphql-type": {
"name": "User",
"kind": "INTERFACE"
}
}After (v2.0):
{
"x-graphql-type-name": "User",
"x-graphql-type-kind": "INTERFACE"
}5. Scalar Naming
Before (v1.x):
{
"definitions": {
"CustomScalars": {
"x-graphql-scalars": {
"DateTime": "...",
"Email": "..."
}
}
}
}After (v2.0):
{
"definitions": {
"DateTime": {
"type": "string",
"format": "date-time",
"x-graphql-scalar": {
"name": "DateTime",
"description": "ISO 8601 date-time"
}
}
}
}Migration Paths
Path A: Automated Migration (Recommended)
Best for:
- Large schema repositories
- Consistent v1.x usage
- Teams with CI/CD pipelines
Steps:
- Install migration tool
- Run migration script
- Review and commit changes
- Validate with test suite
Estimated Time: 1-2 hours for 100+ schemas
Path B: Manual Migration
Best for:
- Small number of schemas (<10)
- Custom/non-standard attributes
- Learning v2.0 conventions
Steps:
- Read breaking changes
- Update schemas manually
- Use validation tool
- Test conversions
Estimated Time: 30 minutes per schema
Path C: Hybrid Migration
Best for:
- Mix of standard and custom schemas
- Complex federation setups
- Gradual rollout
Steps:
- Run automated migration for bulk schemas
- Manually fix edge cases
- Validate all schemas
- Deploy in stages
Estimated Time: 2-4 hours total
Automated Migration
Installation
Node.js:
npm install -g json-schema-x-graphql@2.0.0
# or
npx json-schema-x-graphql@2.0.0 migrateStandalone Script:
curl -O https://raw.githubusercontent.com/json-schema-x-graphql/json-schema-x-graphql/main/scripts/migrate-to-v2.sh
chmod +x migrate-to-v2.shBasic Usage
Migrate Single File:
json-schema-x-graphql migrate --input schema.json --output schema.v2.jsonMigrate Directory:
json-schema-x-graphql migrate --input ./schemas --output ./schemas-v2 --recursiveIn-Place Migration (⚠️ overwrites files):
json-schema-x-graphql migrate --input ./schemas --in-place --backupMigration Script Options
json-schema-x-graphql migrate [options]
Options:
-i, --input <path> Input file or directory
-o, --output <path> Output file or directory
-r, --recursive Process subdirectories
--in-place Overwrite input files
--backup Create .bak backup before in-place
--dry-run Show changes without writing
--report <path> Generate migration report
--strict Fail on any warnings
--federation-only Only migrate federation attributes
--verbose Detailed loggingExample: Dry Run
json-schema-x-graphql migrate \
--input ./schemas \
--dry-run \
--report migration-report.json \
--verboseOutput:
Analyzing schemas...
Found 42 schemas to migrate
Changes Summary:
- x-graphql-keys → x-graphql-federation-keys: 23 occurrences
- x-graphql-shareable → x-graphql-federation-shareable: 15 occurrences
- x-graphql-type (object) → x-graphql-type-name + x-graphql-type-kind: 8 occurrences
- x-graphql-external → x-graphql-federation-external: 12 occurrences
Warnings:
- schema-a.json: Custom attribute 'x-graphql-custom-directive' not migrated (manual review needed)
- schema-b.json: Ambiguous 'x-graphql-type' value (manual review needed)
No files modified (dry run mode).
Report saved to: migration-report.jsonMigration Report
The migration tool generates a JSON report:
{
"summary": {
"totalSchemas": 42,
"migratedSchemas": 40,
"skippedSchemas": 2,
"totalChanges": 58,
"warnings": 2,
"errors": 0
},
"changes": [
{
"file": "user-schema.json",
"path": "$.x-graphql-keys",
"change": "renamed",
"from": "x-graphql-keys",
"to": "x-graphql-federation-keys",
"value": ["id"]
}
],
"warnings": [
{
"file": "schema-a.json",
"message": "Custom attribute 'x-graphql-custom-directive' requires manual review",
"path": "$.x-graphql-custom-directive"
}
],
"skipped": [
{
"file": "invalid-schema.json",
"reason": "Not a valid JSON Schema"
}
]
}Manual Migration
Step-by-Step Checklist
Step 1: Update Federation Attributes
Search and replace in your schemas:
# macOS/Linux
find ./schemas -name "*.json" -type f -exec sed -i '' \
's/"x-graphql-keys"/"x-graphql-federation-keys"/g' {} +
find ./schemas -name "*.json" -type f -exec sed -i '' \
's/"x-graphql-shareable"/"x-graphql-federation-shareable"/g' {} +
find ./schemas -name "*.json" -type f -exec sed -i '' \
's/"x-graphql-external"/"x-graphql-federation-external"/g' {} +
find ./schemas -name "*.json" -type f -exec sed -i '' \
's/"x-graphql-requires"/"x-graphql-federation-requires"/g' {} +
find ./schemas -name "*.json" -type f -exec sed -i '' \
's/"x-graphql-provides"/"x-graphql-federation-provides"/g' {} +
find ./schemas -name "*.json" -type f -exec sed -i '' \
's/"x-graphql-override-from"/"x-graphql-federation-override-from"/g' {} +Step 2: Split x-graphql-type Objects
Find instances:
grep -r "x-graphql-type.*{" ./schemasManual conversion:
Before:
{
"x-graphql-type": {
"name": "User",
"kind": "INTERFACE"
}
}After:
{
"x-graphql-type-name": "User",
"x-graphql-type-kind": "INTERFACE"
}Step 3: Rename x-graphql-type Strings
Find instances:
grep -r '"x-graphql-type":.*"[^{]' ./schemasReplace:
# This is safe for string values only
sed -i 's/"x-graphql-type": "\([^"]*\)"/"x-graphql-type-name": "\1"/g' schema.jsonStep 4: Update Scalar Definitions
Before:
{
"x-graphql-scalars": {
"DateTime": "ISO 8601 date-time"
}
}After:
{
"definitions": {
"DateTime": {
"type": "string",
"format": "date-time",
"x-graphql-scalar": {
"name": "DateTime",
"description": "ISO 8601 date-time"
}
}
}
}Step 5: Add GraphQL-Specific Descriptions (Optional)
If you want different descriptions for GraphQL vs JSON Schema:
{
"type": "object",
"description": "Internal: User database model",
"x-graphql-description": "User account entity",
"properties": {
"id": {
"type": "string",
"description": "Internal: UUID primary key",
"x-graphql-description": "Unique user identifier"
}
}
}Manual Migration Checklist
- Backup all schemas
- Update
x-graphql-keys→x-graphql-federation-keys - Update
x-graphql-shareable→x-graphql-federation-shareable - Update
x-graphql-external→x-graphql-federation-external - Update
x-graphql-requires→x-graphql-federation-requires - Update
x-graphql-provides→x-graphql-federation-provides - Update
x-graphql-override-from→x-graphql-federation-override-from - Split
x-graphql-typeobjects intox-graphql-type-name+x-graphql-type-kind - Rename
x-graphql-type(string) →x-graphql-type-name - Update
x-graphql-scalars→ individualx-graphql-scalardefinitions - Add
x-graphql-descriptionwhere needed (optional) - Run validation tool
- Test conversions
- Update documentation/comments
Validation
Validate Migrated Schemas
Node.js Validator:
npm install -g json-schema-x-graphql@2.0.0
json-schema-x-graphql validate ./schemas/**/*.jsonRust Validator:
cargo install json-schema-x-graphql
json-schema-x-graphql validate ./schemasValidation Output:
Validating 42 schemas...
✓ user-schema.json (34 x-graphql attributes)
✓ product-schema.json (28 x-graphql attributes)
✗ order-schema.json (2 errors, 1 warning)
Error: Unknown attribute 'x-graphql-keys' at $.x-graphql-keys
Did you mean 'x-graphql-federation-keys'?
Error: Invalid value for 'x-graphql-type-kind' at $.x-graphql-type-kind
Expected one of: OBJECT, INTERFACE, UNION, INPUT_OBJECT
Warning: Deprecated attribute 'x-graphql-type' at $.x-graphql-type
Summary:
Total: 42 schemas
Valid: 40
Invalid: 2
Warnings: 1Test Conversions
Convert and Compare:
# Generate GraphQL SDL from migrated schemas
json-schema-x-graphql convert \
--input ./schemas-v2 \
--output ./sdl-output \
--format graphql
# Validate SDL with GraphQL tools
graphql-schema-linter ./sdl-output/**/*.graphqlRun Integration Tests:
# Node.js
npm test
# Rust
cargo test
# Run shared test suite
./scripts/run-integration-tests.shTroubleshooting
Issue: Migration Script Fails
Error: SyntaxError: Unexpected token in JSON
Solution: Ensure all input files are valid JSON:
# Validate JSON before migration
find ./schemas -name "*.json" -exec jsonlint {} \;Issue: Unknown Attribute Warnings
Warning: Unknown attribute 'x-graphql-custom-field'
Solution:
- Check if it’s a typo of a standard attribute
- If custom, add to validator allow-list:
{
"validatorConfig": {
"allowUnknownAttributes": true,
"customAttributes": ["x-graphql-custom-field"]
}
}Issue: Federation Directives Not Working
Error: Unknown directive @key
Solution: Ensure you’re using Apollo Federation schema:
// Node.js
import { buildSubgraphSchema } from "@apollo/subgraph";
const typeDefs = convertedSDL;
const schema = buildSubgraphSchema({ typeDefs });Rust: Use apollo-router-scaffold or Apollo Federation Rust SDK.
Issue: Type Name Conflicts
Error: Type 'User' defined multiple times
Solution:
- Use unique type names across schemas
- Or use federation to extend types:
{
"x-graphql-type-name": "User",
"x-graphql-federation-keys": "id",
"x-graphql-extends": true
}Issue: Descriptions Not Appearing
Problem: Descriptions from JSON Schema not showing in GraphQL
Solution: Check description handling:
- v2.0 prefers
x-graphql-descriptionoverdescription - If
x-graphql-descriptionis empty,descriptionis used - Ensure descriptions are non-empty strings
Issue: Circular References
Error: Maximum call stack size exceeded
Solution: Ensure $ref cycles are handled:
{
"definitions": {
"Node": {
"type": "object",
"properties": {
"parent": { "$ref": "#/definitions/Node" }
}
}
}
}This is valid and should work in v2.0. If it fails, file a bug report.
Migration Examples
Example 1: Simple Schema
Before (v1.x):
{
"type": "object",
"x-graphql-type": "User",
"x-graphql-keys": "id",
"properties": {
"id": { "type": "string" },
"email": { "type": "string" }
}
}After (v2.0):
{
"type": "object",
"x-graphql-type-name": "User",
"x-graphql-federation-keys": "id",
"properties": {
"id": { "type": "string" },
"email": { "type": "string" }
}
}Example 2: Complex Federation Schema
Before (v1.x):
{
"type": "object",
"x-graphql-type": {
"name": "Product",
"kind": "OBJECT"
},
"x-graphql-keys": ["id", "sku"],
"x-graphql-shareable": true,
"properties": {
"id": { "type": "string" },
"sku": { "type": "string" },
"inventory": {
"type": "integer",
"x-graphql-external": true
},
"seller": {
"type": "string",
"x-graphql-provides": "email name"
},
"price": {
"type": "number",
"x-graphql-requires": "inventory"
}
}
}After (v2.0):
{
"type": "object",
"x-graphql-type-name": "Product",
"x-graphql-type-kind": "OBJECT",
"x-graphql-federation-keys": ["id", "sku"],
"x-graphql-federation-shareable": true,
"properties": {
"id": { "type": "string" },
"sku": { "type": "string" },
"inventory": {
"type": "integer",
"x-graphql-federation-external": true
},
"seller": {
"type": "string",
"x-graphql-federation-provides": "email name"
},
"price": {
"type": "number",
"x-graphql-federation-requires": "inventory"
}
}
}Rollback Plan
If you need to roll back to v1.x:
Option 1: Restore from Backup
# If you used --backup flag
find ./schemas -name "*.json.bak" -exec bash -c 'mv "$1" "${1%.bak}"' _ {} \;Option 2: Reverse Migration
# Install v1.x
npm install json-schema-x-graphql@1.x
# Run reverse migration (if available)
json-schema-x-graphql migrate --reverse --input ./schemas-v2 --output ./schemas-v1Option 3: Git Revert
git revert <migration-commit-hash>Support and Resources
Getting Help
- Documentation: X-GraphQL Docs
- Issues: GitHub Issues
- Discussions: GitHub Discussions
Additional Resources
- Quick Start Guide - Get started with v2.0
- Attribute Reference - Complete attribute catalog
- Common Patterns - Real-world examples
- Implementation Plan - Technical details
Version: 2.0.0
Last Updated: January 2025
Status: ✅ Complete