|
| 1 | +--- |
| 2 | +title: Easier Gradual Schema Migrations with Progressive Overrides |
| 3 | +description: |
| 4 | + Safer and controlled migrations with Progressive Override that allows gradual schema changes. |
| 5 | +date: 2025-10-29 |
| 6 | +authors: [arda] |
| 7 | +--- |
| 8 | + |
| 9 | +import { Tabs } from '@theguild/components' |
| 10 | + |
| 11 | +**Schema migrations just got a lot safer.** We're thrilled to introduce Progressive Override in Hive |
| 12 | +Gateway and Hive Router - enabling you to gradually migrate fields between subgraphs with zero risk |
| 13 | +and full control. |
| 14 | + |
| 15 | +Moving fields between subgraphs has always been risky. Traditional approaches require coordinated |
| 16 | +releases, no way to gradually test changes, and zero tolerance for errors. With Progressive |
| 17 | +Override, you can now: |
| 18 | + |
| 19 | +- **A/B test** field migrations before full rollout |
| 20 | +- **Reduce risk** with percentage-based traffic control |
| 21 | +- **Test safely** with internal users first, then gradually expand to all traffic |
| 22 | +- **Rollback instantly** if anything goes wrong |
| 23 | + |
| 24 | +No more stressful schema migrations - just smooth, controlled transitions that you control |
| 25 | +completely. |
| 26 | + |
| 27 | +## Simple Percentage-Based Rollouts |
| 28 | + |
| 29 | +The easiest way to get started is with **built-in percentage rollouts**. No gateway configuration |
| 30 | +needed - just add a `percent(x)` label to your `@override` directive. |
| 31 | + |
| 32 | +**Step 1:** Import the `@override` directive in your subgraph schema: |
| 33 | + |
| 34 | +```graphql |
| 35 | +extend schema @link(url: "https://specs.apollo.dev/federation/v2.7", import: ["@key", "@override"]) |
| 36 | +``` |
| 37 | + |
| 38 | +**Step 2:** Add the field to your new subgraph with progressive override: |
| 39 | + |
| 40 | +```diff |
| 41 | +type Bill @key(fields: "id") { |
| 42 | + id: ID! |
| 43 | ++ amount: Int! @override(from: "Payments", label: "percent(20)") |
| 44 | +} |
| 45 | +``` |
| 46 | + |
| 47 | +That's it! **20% of traffic** for the `amount` field will now route to your new `Billing` subgraph, |
| 48 | +while **80% continues** to use the `Payments` subgraph. |
| 49 | + |
| 50 | +### How It Works |
| 51 | + |
| 52 | +- **Same query = same result**: The percentage is calculated per operation, ensuring consistency |
| 53 | +- **No configuration needed**: The `percent(x)` syntax works automatically |
| 54 | +- **Gradual rollout**: Start with 20%, monitor for a day, increase to 50%, then 100% |
| 55 | +- **Safe migration**: Both subgraphs serve the field simultaneously until you reach 100% |
| 56 | + |
| 57 | +When you're ready to commit the change completely, simply bump the percentage to 100% and remove the |
| 58 | +field from the old subgraph. |
| 59 | + |
| 60 | +## Advanced: Custom Labels & Feature Flags |
| 61 | + |
| 62 | +Need more control than percentages? **Custom labels** let you route traffic based on specific |
| 63 | +criteria - user groups, feature flags, request headers, or any logic you need. |
| 64 | + |
| 65 | +Perfect for: |
| 66 | + |
| 67 | +- **Beta testing** with specific user groups |
| 68 | +- **Internal testing** before public release |
| 69 | +- **Integration** with LaunchDarkly or other feature flag services |
| 70 | +- **Header-based routing** (e.g., `x-user-group: beta`) |
| 71 | + |
| 72 | +```diff |
| 73 | +type Bill @key(fields: "id") { |
| 74 | + id: ID! |
| 75 | ++ amount: Int! @override(from: "Payments", label: "activate-beta-feature") |
| 76 | +} |
| 77 | +``` |
| 78 | + |
| 79 | +### Configure Your Gateway |
| 80 | + |
| 81 | +Now tell your gateway when to activate this label. You can base the decision on headers, environment |
| 82 | +variables, user IDs, or any other criteria. |
| 83 | + |
| 84 | +The following example shows how to activate the `activate-beta-feature` label if `x-user-group` |
| 85 | +header is set to `beta`. |
| 86 | + |
| 87 | +<Tabs items={['Hive Gateway', 'Hive Router']}> |
| 88 | + <Tabs.Tab> |
| 89 | + {/* Hive Gateway Content */} |
| 90 | + ```ts |
| 91 | + import { defineConfig, type GatewayContext } from '@graphql-hive/gateway'; |
| 92 | + |
| 93 | + export const gatewayConfig = defineConfig({ |
| 94 | + progressiveOverride(label: string, context: GatewayContext) { |
| 95 | + if (label === 'activate-beta-feature' && context.request.headers.get('x-user-group') === 'beta') { |
| 96 | + // Activate `activate-beta-feature` feature flag |
| 97 | + return true; |
| 98 | + } |
| 99 | + return false; |
| 100 | + } |
| 101 | + }); |
| 102 | + ``` |
| 103 | + |
| 104 | + </Tabs.Tab> |
| 105 | + <Tabs.Tab> |
| 106 | + {/* Hive Router Content */} |
| 107 | + ```yaml |
| 108 | + override_labels: |
| 109 | + activate-beta-feature: |
| 110 | + # Activate if the x-user-group header is set to beta |
| 111 | + expression: '.request.headers."x-user-group" == "beta"' |
| 112 | + ``` |
| 113 | + </Tabs.Tab> |
| 114 | +</Tabs> |
| 115 | +
|
| 116 | +### Why You'll Love Progressive Override |
| 117 | +
|
| 118 | +Transform how you deploy GraphQL schema changes: |
| 119 | +
|
| 120 | +**🎯 Zero-Risk Rollouts** Start with 5% of traffic, watch your metrics, increase to 50%, then 100%. |
| 121 | +Sleep better knowing you can rollback instantly. |
| 122 | +
|
| 123 | +**⚡ Faster Feature Delivery** No more waiting for coordinated releases. Test new implementations in |
| 124 | +production with real traffic before committing. |
| 125 | +
|
| 126 | +**🧪 Real A/B Testing** Compare behavior between old and new implementations side-by-side with the |
| 127 | +same queries. Make data-driven decisions. |
| 128 | +
|
| 129 | +**🔒 Built-in Safety** Both implementations run in parallel until you reach 100%. If something |
| 130 | +breaks, just lower the percentage or remove the label. |
| 131 | +
|
| 132 | +**👥 Smarter Testing** Route specific user groups (beta testers, internal users) to new |
| 133 | +implementations. Get feedback before global release. |
| 134 | +
|
| 135 | +**📊 Better Monitoring** Compare performance metrics, error rates, and user behavior across both |
| 136 | +implementations in real-time. |
| 137 | +
|
| 138 | +> You can use this feature with LaunchDarkly or any other feature flagging service by integrating it |
| 139 | +> into your gateway/router configuration. See |
| 140 | +> [the example with Hive Gateway](https://github.com/graphql-hive/gateway/tree/main/examples/launchdarkly-override) |
| 141 | +
|
| 142 | +## Ready to Make Schema Migrations Stress-Free? |
| 143 | +
|
| 144 | +**Progressive Override is live now** in both Hive Gateway and Hive Router. Start using it today to |
| 145 | +make your GraphQL schema migrations safer and more controlled. |
| 146 | +
|
| 147 | +### Quick Start Links |
| 148 | +
|
| 149 | +**For Hive Gateway users:** 👉 |
| 150 | +[Read the Gateway Documentation](/docs/gateway/other-features/progressive-override) |
| 151 | +
|
| 152 | +**For Hive Router users:** 👉 |
| 153 | +[Read the Router Documentation](/docs/router/configuration/override_labels) |
| 154 | +
|
| 155 | +**See it in action:** 👉 |
| 156 | +[LaunchDarkly Integration Example](https://github.com/graphql-hive/gateway/tree/main/examples/launchdarkly-override) |
| 157 | +
|
| 158 | +--- |
| 159 | +
|
| 160 | +Questions or want to share how you're using Progressive Override? We'd love to hear from you! |
0 commit comments