DEV Community

Cover image for What if GraphQL Was Your Database?
James Ross
James Ross

Posted on

What if GraphQL Was Your Database?

We've been doing this backwards for decades.

You define your data model in SQL. Then you write a GraphQL schema. Then TypeScript interfaces. Then Zod validators. Then API docs. Five different representations of the exact same data structure, maintained by hand, drifting apart with every sprint.

One missed migration and suddenly your frontend expects a field that doesn't exist. One mistyped interface and runtime errors cascade through production. We've normalized this insanity as "just how web development works."

But what if we inverted the entire paradigm?

GraphQL Isn't Just an API Layer

GraphQL already expresses your data model better than SQL. It has types, relationships, non-nullability, and documentation built in. It's human-readable. It evolves gracefully. Most importantly: it's how developers actually think about data.

So why are we still treating SQL as the source of truth and GraphQL as the derived artifact?

Wesley flips the script. Write your schema in GraphQL once, augmented with semantic directives, and generate your entire data layer: Postgres DDL, TypeScript types, Zod validators, pgTAP tests, and safe migrations.

One schema. Everything generated. Zero drift. Migrations for free.

How It Works

How it Works

Wesley extends GraphQL with intuitive directives that tell it how to translate your domain model into working infrastructure:

type Organization @wes_table {
  id: ID! @wes_pk
  name: String! @wes_unique
  slug: String! @wes_unique @wes_index
  created_at: DateTime! @wes_default(value: "now()")
}

type User @wes_table @wes_tenant(by: "org_id") {
  id: ID! @wes_pk @wes_default(value: "gen_random_uuid()")
  org_id: ID! @wes_fk(ref: "Organization.id")
  email: String! @wes_unique @wes_index
  password_hash: String! @wes_sensitive
  created_at: DateTime! @wes_default(value: "now()")
  updated_at: DateTime! @wes_default(value: "now()")
}
Enter fullscreen mode Exit fullscreen mode

From this single schema, Wesley compiles:

PostgreSQL DDL with proper constraints, indexes, and foreign keys

CREATE TABLE organizations (
  id UUID PRIMARY KEY,
  name TEXT UNIQUE NOT NULL,
  slug TEXT UNIQUE NOT NULL,
  created_at TIMESTAMPTZ DEFAULT now() NOT NULL
);

CREATE INDEX idx_organizations_slug ON organizations(slug);

CREATE TABLE users (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  org_id UUID NOT NULL REFERENCES organizations(id),
  email TEXT UNIQUE NOT NULL,
  password_hash TEXT NOT NULL,
  created_at TIMESTAMPTZ DEFAULT now() NOT NULL,
  updated_at TIMESTAMPTZ DEFAULT now() NOT NULL
);
Enter fullscreen mode Exit fullscreen mode

TypeScript types that stay in sync automatically

interface Organization {
  id: string;
  name: string;
  slug: string;
  created_at: Date;
}

interface User {
  id: string;
  org_id: string;
  email: string;
  password_hash: string;
  created_at: Date;
  updated_at: Date;
}
Enter fullscreen mode Exit fullscreen mode

Zod validators for runtime safety

const UserSchema = z.object({
  id: z.string().uuid(),
  org_id: z.string().uuid(),
  email: z.string().email(),
  password_hash: z.string().min(1),
  created_at: z.date(),
  updated_at: z.date(),
});
Enter fullscreen mode Exit fullscreen mode

pgTAP tests to verify your schema

SELECT has_table('users');
SELECT has_column('users', 'email');
SELECT col_is_unique('users', 'email');
SELECT has_fk('users', 'org_id', 'organizations', 'id');
Enter fullscreen mode Exit fullscreen mode

And most importantly: safe, phased migrations. Wesley generates expand → backfill → validate → switch → contract migrations that minimize downtime and lock contention.

Why It's Safe to Ship

SHA-locked HOLMES

Every Wesley compilation produces a SHA-locked evidence bundle, a cryptographic proof that your changes are safe. The verification system analyzes:

  • Schema coverage and completeness
  • Migration risk assessment
  • Test confidence metrics
  • Historical deployment success

Before your migrations touch production, they're rehearsed in an isolated shadow environment. The system captures lock levels, timing data, and potential failure modes. Only verified, tested changes get deployed.

This isn't "trust me bro, it'll probably work." It's cryptographically verifiable proof that your migration was validated. Deploy database changes on Friday with confidence.

Row-Level Security Built In

Multi-tenant applications need data isolation. With the @wes_tenant directive, Wesley generates complete RLS policies automatically:

type Document @wes_table @wes_tenant(by: "org_id") {
  id: ID! @wes_pk
  org_id: ID! @wes_fk(ref: "Organization.id")
  title: String!
  content: String!
}
Enter fullscreen mode Exit fullscreen mode

Wesley guarantees users can only access their organization’s data, and brings the pgTAP tests to demonstrate it. No manual policy writing. No forgotten WHERE clauses. Security by default.

The Paradigm Shift

The revolution isn't the code generation. It's the inversion of thinking.

Everyone assumes SQL comes first because "that's where the data lives." But data doesn't live in SQL. It lives in our mental models. GraphQL expresses those models better than SQL ever could.

Wesley makes the computer work the way our brains work, not the other way around.

What's Next

Wesley is open source and ready for early adopters:

Wesley is just getting started. The roadmap includes:

  • Visual schema editor for designing your data model
  • Time-travel debugging through schema evolution
  • Multi-database support (MySQL, SQLite, and more)
  • Framework-specific plugins (Next.js, Remix, SvelteKit)
  • AI-powered schema optimization suggestions
  • and more...

The future is schema-first. The future is Wesley.

The future is schema-first

Go on then. Deploy on a Friday. I dare you.


Wesley is named after Wesley Crusher from Star Trek: The Next Generation, the brilliant ensign who saw possibilities others couldn't. Like his namesake, Wesley (the tool) transcends conventional thinking to solve problems in ways that seem obvious only in hindsight.

Top comments (0)