Skip to main content
Version: Next

PostGraphile schema-only usage

The PostGraphile library mode gives you a lot of excellent features for running your own GraphQL server. However, if you want to execute a PostGraphile query in Node.js without having to go through HTTP you can use some other exported functions that PostGraphile provides.

If you're looking for Apollo Client SSR support for PostGraphile without a network roundtrip, check out GraphileApolloLink in Graphile Starter.

Getting the schema

The first function you will need is makeSchema (or watchSchema if you want to get a new schema each time the database is updated) which creates your PostGraphile GraphQL schema by introspecting your database.

The makeSchema function accepts a configuration preset and returns a promise to a SchemaResult, which is an object containing:

  • schema - the GraphQL schema
  • resolvedPreset - the resolved preset
import { makeSchema } from "postgraphile";
import preset from "./graphile.config.js";

const { schema, resolvedPreset } = await makeSchema(preset);

If you already have a PostGraphile instance (pgl), you can instead get the GraphQL schema and resolvedPreset via:

const { schema, resolvedPreset } = await pgl.getSchemaResult();

Easy execution: grafast()

Now that you have schema and resolvedPreset, you can execute a GraphQL query via:

import { grafast } from "grafast";

const { data, errors } = await grafast({
requestContext: {
// This is the "request context" - it is **NOT** the GraphQL context
source: /* GraphQL */ `
query MyQuery {
variableValues: {},

grafast() is equivalent to graphql() except it also accepts two additional optional entries in the args object: the resolvedPreset and the request context requestContext. If you pass these parameters then grafast will take care of building the GraphQL context for you based on what is in your preset.


Do not confuse requestContext with the GraphQL context; requestContext is the parameter passed to your preset.grafast.context(requestContext) callback (and any plugins that need it) containing details of where the request came from. In a node HTTP web server it would typically be something like requestContext = { node: { req, res } } and would be used to extract things like the Authorization header to determine who is making the request. Different servers and situations may add alternative or additional information.

Execution with hookArgs()

If you do not (or can not) pass these parameters to grafast() then you will need to call hookArgs() yourself to build the GraphQL context that PostGraphile will need in order to communicate with the database. This also means that you're taking care of parsing and validating the GraphQL request yourself.


If you're doing this inside a server framework, they will often give you a way to hook the args before they're dispatched to execute - that is where you would call hookArgs().

Here's a full example:

import { makeSchema } from "postgraphile";
import { parse, validate } from "postgraphile/graphql";
import { hookArgs, execute } from "postgraphile/grafast";

import preset from "./graphile.config.js";

// Trigger schema building outside of `executeQuery` so we only do it once:
const schemaResultPromise = makeSchema(preset);

* Given a request context `requestContext`, GraphQL query text `source` and
* optionally variable values and operation name, execute the given GraphQL
* operation against our schema and return the result.
export async function executeQuery(
requestContext: Grafast.RequestContext,
source: string,
variableValues?: Record<string, unknown> | null,
operationName?: string,
) {
// Finish loading the schema:
const { schema, resolvedPreset } = await schemaResultPromise;

// Parse the GraphQL query text:
const document = parse(source);

// Validate the GraphQL document against the schema:
const errors = validate(schema, document);
if (errors.length > 0) {
throw new Error(`Validation error(s) occurred`, { cause: errors });

// Prepare the execution arguments:
const args = await hookArgs(

// Execute the request using Grafast:
return await execute(args, resolvedPreset);