This guide will walkthrough creating a new Grafbase project from scratch.

Begin by executing the following command inside a new or existing project's directory:

npx grafbase init

After the setup, you'll be greeted with a message similar to:

✨ Your project was successfully set up for Grafbase! Your new configuration can be found at ./grafbase.config.ts We've added our SDK to your package.json, make sure to install dependencies before continuing.

Finally, install the dependencies:

npm install

Grafbase automatically introspects your Postgres database schema to generate all the GraphQL queries and mutations necessary to create, read, update, delete, as well as filter, paginate and order data.

You should already have a Postgres setup. You will need your connection string.

Open grafbase.config.ts and initialize your graph using the Grafbase SDK:

import { config, connector, graph } from '@grafbase/sdk' const g = graph.Standalone()

Now configure a new Postgres data source:

const pg = connector.Postgres('Postgres', { url: g.env('DATABASE_URL'), })

You'll want to add your connection string to the file .env:


Finally, connect pg as a datasource to the graph:


You can now use the Grafbase CLI to run your GraphQL API locally.

Run the following command to start the local development server:

npx grafbase dev

Once started, you can navigate to to explore and execute the generated GraphQL operations.

Depending on the tables you have in your database, your GraphQL schema will look something like this:

type PostgresQuery { user(by: PostgresUserByInput!): PostgresUser userCollection( filter: PostgresUserCollection first: Int last: Int before: String after: String orderBy: [PostgresUserOrderByInput] ): PostgresUserConnection } type PostgresMutation { userDelete(by: PostgresUserByInput!): PostgresUserMutation userDeleteMany( filter: PostgresUserMutationCollection! ): PostgresUserBatchMutation userCreate(input: PostgresUserInput!): PostgresUserMutation userCreateMany(input: [PostgresUserInput!]!): PostgresUserBatchMutation userUpdate( by: PostgresUserByInput! input: PostgresUserUpdateInput! ): PostgresUserMutation userUpdateMany( filter: PostgresUserMutationCollection! input: PostgresUserUpdateInput! ): PostgresUserBatchMutation }

You can add as many databases as you like using the Postgres connector. They will all be namespaced using the name provided to the connector.

Sometimes there will be data in your database that you want to use to compute values on the fly. Grafbase Resolvers allow you to write custom resolvers that run at the edge with your code.

In this example, we'll assume the table is called User that has the columns firstName and lastName.

Let's learn how we can extend a table (GraphQL Type) with some custom code that returns the full name of a user.

Inside grafbase.config.ts add the following:

g.extend('PostgresUser', { fullName: { returns: g.string(), resolver: 'fullname', }, })

We extend the GraphQL schema using the extend() function, passing it the name of the Connector and Type — PostgresUser. We then specify the return type and file name that resolves the response.

Now create the file resolvers/fullname.ts and add the following:

export default async function FullNameResolver({ firstName, lastName }) { return `${firstName} ${lastName}` }

The code here isn't too important, but it fetches firstName and lastName fields from the root argument and uses it to compute the full name.

It's important you request all three fields when executing the GraphQL query:

query { neon { userCollection(first: 10) { edges { node { firstName lastName fullName } } } } }

Inside Pathfinder you can monitor the time it takes to execute GraphQL operations against your connected database. It doesn't matter how many times you make the same request, Grafbase will always go to the database to get the results.

Response times

We can improve this by enabling GraphQL Edge Caching. For simplicity, we'll cache everything but you can add additional configuration rules to only cache things you want, as well as configure different values for the stale while revalidate and max age values.

Update the config object inside grafbase.config.ts to be:

export default config({ graph: g, cache: { rules: [ { types: ['Query'], maxAge: 120, staleWhileRevalidate: 120, }, ], }, })

Now if you make the same request, you'll see the response times are much faster!

Cached Response Times

Once you're ready to deploy your application to production, you can do this using a GitHub repository or the Grafbase CLI.

It's recommended you use GitHub so that deployments are automatically taken care of during pull requests and branch merges.

  1. Create a Grafbase account
  2. Create a New Project
  3. Commit your changes to a GitHub repository
  4. Connect your GitHub repository to Grafbase
  5. Add the DATABASE_URL as an environment variable when creating a new project
  6. Update your host (Netlify, Vercel, Fly, etc.) with the new GraphQL API endpoint provided by Grafbase

That's it!

Was this page helpful?