Rails with GraphQL

Rails is still one of the fastest ways to get an API on disk. This note is the small setup I used for a Rails API app with GraphQL and PostgreSQL.
It is not a manifesto for GraphQL. It is the shortest path I used when I wanted Rails to handle the app shell and GraphQL to own the client-facing query shape.
Install Ruby and Rails
I used rbenv for Ruby versions:
brew install rbenv
rbenv install 3.0.1Install Rails and Bundler:
gem install rails
gem install bundlerYou can list available Ruby versions if you want a different one:
rbenv install --listCreate an API-only app
Start Rails without the default frontend stack and use PostgreSQL:
rails new app --api -d postgresql
cd appAdd the GraphQL gem:
bundle add graphqlGenerate the GraphQL skeleton:
rails generate graphql:installRails puts the GraphQL code under app/graphql. I inspect that directory before
adding any real models, because the generator creates a lot of decisions that
are easy to ignore at first.
Why this shape works
Rails handles the application shell: routing, database config, models, migrations, validations, and environment wiring. GraphQL gives clients a typed query surface without creating a custom REST endpoint for every screen.
The setup is small enough that you can inspect all of it. That matters more than the generator output. I usually check the generated schema, the base query type, and how errors are returned before building features. If those pieces are muddy, the app will stay muddy.
What to inspect next
After the generator runs, I would check these files before building features:
app/graphql/types/query_type.rbapp/graphql/types/mutation_type.rbapp/graphql/app_schema.rb- the generated controller route for GraphQL requests
The point is to understand the boundary before adding models. Which errors are returned to clients? Are exceptions hidden or exposed? Where does authorization belong? Are mutations named around domain actions, or are they just CRUD wrappers around tables?
Rails makes it easy to move quickly, but GraphQL schemas age badly when every screen gets its own shape. I prefer starting with a small query surface and a few intentional mutations. The schema should describe product operations, not leak the database one table at a time.