DEV Community

Cover image for Switching from Hasura to Grafbase: A Step-by-Step Migration Guide
Moronfolu Olufunke for Hackmamba

Posted on

Switching from Hasura to Grafbase: A Step-by-Step Migration Guide

Hasura gained popularity and became widely adopted for its ability to quickly let teams spin up a GraphQL API on top of a relational database, particularly PostgreSQL. That speed makes it a strong early-stage choice. But as systems grow, many teams start running into architectural limits like:

  • Schema rigidity: Hasura’s API layer is tightly coupled to the database schema, which makes it harder to evolve APIs or decouple logic over time.
  • Architectural control: Fine-grained control over resolver logic, caching, or gateway behavior is challenging to achieve.
  • Vendor lock-in: Hasura’s proprietary metadata format introduces vendor lock-in and complicates migration efforts.
  • Limited extensibility: Adding functionality through actions or remote schemas often requires managing external services, adding friction to development workflows.

If you're starting to hit those limits and exploring alternatives, a more robust solution like Grafbase should be on your radar. Grafbase’s schema-first model supports multiple data sources out of the box, enables declarative federation, and avoids the need to stitch or host separate subgraph services. With the Postgres extension, you can introspect your schema and publish it directly into a federated GraphQL API while controlling how your gateway behaves.

This guide provides practical migration steps to guarantee a smooth migration from Hasura to Grafbase, offers side-by-side comparisons with Hasura, and helps you determine whether Grafbase is the right next step for your team.

Grafbase vs. Hasura: Comparing key concepts

This section compares key features between Hasura and Grabase to help you understand how these core features are translated and handled on each platform.

Feature Hasura Grafbase
Schema management Auto-generated from Postgres Schema Definition Language (SDL) first, explicit schema definition, declarative GraphQL schema (schema.graphql)
Data sources PostgreSQL (primary), Remote schemas, REST via actions PostgreSQL, REST, gRPC, Snowflake, Kafka via extensions
API Gateway Basic built-in API layer; limited control over gateway behavior GraphQL Gateway with custom resolvers, and federated subgraphs
CLI hasura-cli for migrations, metadata, and project management grabase CLI for local dev, schema introspection, publishing, and gateway setup
Schema registry No native schema registry or versioning; schema can be exported via introspection or the console Built-in schema registry, versioning, schema validation with Grafbase check

To dig deeper into how the two tools compare, this Hasura alternative guide covers more architectural and workflow-level differences. You’ll also find platform-specific details in the Grafbase docs if you're exploring a larger rollout across teams or environments.

Once you are familiar with what Grafbase offers, the next step is learning how to implement it. The following sections guide you through each stage of the process, including exporting Hasura metadata, generating your Grafbase schema, configuring subgraphs, and deploying via the Grafbase Gateway.

Preparing for migration

Before starting your migration, audit your current setup and align your team on what a successful switch looks like. Use this checklist to make sure your team is ready for migration:

  • Audit Hasura setup: List all tables, relationships, permissions, actions, event triggers, and remote schemas in use.
  • Identify business logic: Document any implemented custom logic.
  • Map auth flows: Understand your current authentication and authorization setup.
  • List integrations: Note any webhooks, REST endpoints, or third-party integrations.
  • Set clear migration goals: Get your team on board, make sure everyone agrees on the plan, and define the migration objectives.

Migration tools

You’ll need to have these tools installed:

Step-by-step migration process

We’ll build a small demo project with features like custom actions and remote schema (REST API) to demonstrate how to safely migrate a real Hasura setup to Grafbase.

1. Export Hasura metadata

As mentioned earlier, you need to audit your Hasura setup before the migration process. Start by exporting your Hasura metadata via the CLI by running:

hasura metadata export
Enter fullscreen mode Exit fullscreen mode

Alternatively, you can also use the Hasura console or API which is part of the Hasura open source framework.

This will instantly generate a metadata containing configuration data about your Hasura actions, remote schemas, custom types, and more. Study them carefully, as these will help you shape your Grafbase schema.

2. Generate a federated GraphQL schema

The next step is to generate GraphQL schema. Even if your database is complex, the Grafbase PostgreSQL extension makes it easier to convert and translate the exported Hasura metadata for use in Grafbase. This extension also helps teams generate a GraphQL schema from an existing PostgreSQL database.

To generate the GraphQL schema, follow these steps:
a. Make sure you have installed the Grabase CLI and the Grafbase Postgres extension.
b. Next, create a grafbase-postgres.toml configuration file in your project and add this:

# Change this to reflect the version of the extension you want to use.
extension_url = "https://grafbase.com/extensions/postgres/0.4.7"

# The generated SDL needs to know in which schema the type comes from.
# If the schema name is not written in the schema, Grafbase will use this value.
default_schema = "public"

# The name of the database in the Grafbase configuration.
database_name = "default"
Enter fullscreen mode Exit fullscreen mode

c. Next, introspect your database and generate a GraphQL schema by running:

grafbase postgres \
  --database-url "postgres://postgres:user@password:5432/your_db_name" \
  introspect > schema.graphql
Enter fullscreen mode Exit fullscreen mode

This will generate a schema.graphql file that represents your database schema.

3. Configure the project

Next, within your project, create a grafbase.toml file to configure the Postgres extension and point to the generated schema:

[extensions.postgres]
# Change to the latest version.
version = "0.4.7"

[[extensions.postgres.config.databases]]
name = "default" # This must match the name in the grafbase-postgres.toml
url = "postgres://postgres:user@password:5432/your_db_name"

[subgraphs.postgres]
schema_path = "./schema.graphql"
Enter fullscreen mode Exit fullscreen mode

Test the success of the SDL generation and launch the development server by running:

grafbase dev
Enter fullscreen mode Exit fullscreen mode

Navigate to http://127.0.0.1:5000 in your browser to explore the generated schema.

With the Postgres subgraph deployed, let’s now federate an external REST API into the graph.

4. Publish the Postgres subgraph

Once you're ready, first create a new graph in the Grafbase Dashboard. Next, publish the Postgres schema to the Grafbase platform as a virtual subgraph using this command:

grafbase publish \
--name postgres \
<name-of-org>/<name-of-graph>@<branch> \
--schema schema.graphql \
--virtual
Enter fullscreen mode Exit fullscreen mode

This lets you map your database into a federated graph with no intermediate API layer, no stitching, and no subgraph service to maintain.

You can do this for as many schemas as you have. But what happens if you have REST APIs to federate?

5. Migrate remote schemas

Grafbase provides different extensions to extend federated graphs. One such extension is the REST extension, which, when integrated, enables you to define REST endpoints and map them to GraphQL fields using two directives: @restEndpoint and @rest .

To use this REST extension, you must create a new schema file separate from your Postgres schema, as Grafbase requires that Postgres and REST extensions reside in different subgraphs.

This example uses the publicly available fake store REST API. Follow these steps to see how you will use it in Grafbase:

a. Add the REST extension: In the grafbase.toml file, add the code below to install the REST extension, then add the link to the new REST schema you created. Like so:

[extensions.rest]
version = "0.4.1"

[subgraphs.rest]
schema_path = "./rest-schema.graphql"
Enter fullscreen mode Exit fullscreen mode

Run grafbase extension install to install the newly added REST extension into the grafbase_extensions directory. This command installs any extensions declared in the grafbase.toml that are not yet installed.

b. Define the REST schema: In the newly created REST schema file, add this code:

extend schema
  @link(
    url: "https://grafbase.com/extensions/rest/0.4.1"
    import: ["@restEndpoint", "@rest"]
  )
  @restEndpoint(name: "restProducts", baseURL: "https://fakestoreapi.com")
type RestProducts {
  title: String!
  price: Float!
  description: String!
  category: String!
  image: String!
}
type Query {
  getAllRestProducts: [RestProducts!]!
    @rest(
      method: GET
      endpoint: "restProducts"
      path: "/products"
      selection: """
      [.[] | {
        title: .title,
        price: .price,
        description: .description,
        category: .category,
        image: .image
      }]
      """
    )
}
Enter fullscreen mode Exit fullscreen mode

This code fetches product data from a public REST API (fakestoreapi.com) and exposes it as a GraphQL query (getAllRestProducts) using Grafbase’s REST extension.

Test locally by saving, stopping your local development environment, and then running grafbase dev again. It’s as simple as that!

c. Publish the REST subgraph: Now, you can publish this new subgraph to the Grafbase platform by running the deploy command you used previously, but with a change to reflect the name of the subgraph you want to publish and the path to the current local schema:

grafbase publish \
--name rest \
<name-of-org>/<name-of-graph>@<branch> \
--schema rest-schema.graphql \
--virtual
Enter fullscreen mode Exit fullscreen mode

Integrating REST APIs typically requires setting up Actions in Hasura, which can involve complex configuration. By contrast, as demonstrated above, this was accomplished in just three straightforward steps on Grafbase.

6. Combine and deploy subgraphs with the Grafbase Gateway

After publishing the new subgraph, you can deploy the federated graph using the Grafbase Gateway. The gateway automatically keeps up with subgraph updates and unifies different subgraphs into a single federated graph for querying. In this case, it will federate the Postgres and REST subgraphs.

Follow these steps to deploy:
a. Create an access token in the Grafbase organization settings.

b. Export the access token and start the gateway using this command:

export GRAFBASE_ACCESS_TOKEN="ey..." //exported token
Enter fullscreen mode Exit fullscreen mode

c. Start the gateway by running:

grafbase-gateway --graph-ref name-of-graph --config grafbase.toml
Enter fullscreen mode Exit fullscreen mode

The --config argument is optional, but to start the gateway with a graph ref, the access token is mandatory.

You now have the schema registry populated, the gateway set up, and the federated graph on Grafbase up and running. You can send queries to the Grafbase Gateway and observe it in action with your Federated Graph.

Refer to the Grafbase Postgres extension guide for more information on features, configuration options, and running the gateway.

Post-migration tips

On successful migration from Hasura to Grafbase, it's also essential to validate and optimize your new setup. Here’s a checklist of what to test and monitor post-migration:

Query parity between systems

Confirm that all critical and/or complex queries and mutations behave as expected and return the same data structures and values as they did in Hasura.

Additionally, to verify schema consistency between the exported Hasura metadata and the generated schema on Grafbase, run:

diff name_ofhasura_metadata.graphql name_of_grafbase_schema.graphql
Enter fullscreen mode Exit fullscreen mode

This will show you line-by-line differences between your Hasura-generated schema and your Grafbase schema, helping you identify mismatches or missing types and fields.

Set up schema checks

Using the grafbase check command, you can check your schema against the Grafbase Platform. This will help you safeguard against introducing breaking changes or errors into your GraphQL API, especially when working in multiple teams. Read more on the dedicated docs page.

Deployment configuration (cloud services or self-hosted)

Validate that tokens, secrets, and environment variables are securely stored and accessible in your cloud or container platform.

Subgraphs management

Organize schemas and group related functionality into logical subgraphs for modularity and clarity.

Observe latency and performance changes

Without relying on external tools like Grafana or Datadog, Grafbase provides built-in solutions for telemetry and observability features. You can benchmark workload and key metrics after migration, and use the Grafbase dashboard to view insights and analytics on error rates and slow responses, helping you to detect regressions proactively.

Horizontal scaling

Monitor how your federated graph performs as you add more subgraphs or services. Grafbase’s gateway is designed to scale, but you’ll still want observability in place.

There are additional steps to verify success after migration, but taking the above as a starting point is a great approach.

Troubleshooting mixing resolver extensions in the same subgraph

You might encounter the following error when starting the federated gateway:

Error: could not start the federated gateway
Caused by: Error validating federated SDL: Selection Set Resolver extension postgres-0.4.1 cannot be mixed with other resolvers in subgraph 'postgres', found rest-0.4.1
Enter fullscreen mode Exit fullscreen mode

Cause: This error occurs when you try to use both the Postgres and REST resolver extensions in a single subgraph (in this case, using REST extension in the Postgres subgraph). Grafbase doesn't support combining multiple selection set resolver extensions (such as @postgres and @rest) within the same subgraph.

Solution: Separate the conflicting extensions into distinct subgraphs. For example, if your Postgres subgraph already uses the @postgres extension, create a new subgraph (e.g., rest) for REST-based resolvers and configure it independently in your grafbase.toml.

These benefits are available to you after migration

Now that you have seen how to easily migrate from Hasura to Grafbase, here’s a summary of some advantages that the highlighted Grafbase features provide for your team and how they help you scale beyond Hasura’s limitations.

Hasura limitations Grafbase solution
Schema rigidity Grafbase uses a schema-first approach. As such, it lets you compose your GraphQL schema from multiple sources (databases, APIs) rather than binding it directly to a single database schema.
Architectural control Grafbase provides more granular control over caching strategies and gateway behavior. Its Edge Gateway allows you to orchestrate all your data fetching and optimize performance at the gateway layer, rather than being restricted to database-driven resolvers.
Vendor lock-in Grafbase avoids proprietary metadata formats tightly coupled to its runtime. Its approach is to use standard GraphQL schemas and open configuration, making migration and integration with other tools less risky and complex.
Limited extensibility Grafbase is designed for extensibility, allowing you to connect multiple APIs and services and implement domain-specific logic directly within your schema.

Wrapping up

For teams running into Hasura’s limitations, exploring alternatives like Grafbase provides benefits that make it a worthwhile move.. The benefits include long-term flexibility and maintainability, improved API architecture, enhanced developer productivity, and experience. Grafbase also provides more control over your GraphQL gateway and production-grade federation support.

Ready to try it out? Get started with Grafbase and migrate your federated graph to Grafbase in minutes.

Top comments (0)