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.
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. That is where the schema,
object types, mutations, and resolvers live.
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 pile of custom REST endpoints for every screen.
The setup is small enough that you can inspect all of it. That matters more than the generator output. The first thing I check after install is the generated schema, the base query type, and how errors are returned. If those are clear, the rest of the app can grow without much ceremony.
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 goal 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.