Skip to content

Performance Benchmarks

When Rolls-Royce was asked about the horsepower of their engine, the answer was “sufficient.” That is also the honest answer for FraiseQL’s throughput.

Independent data from VelocityBench — an open-source suite testing 35 frameworks under identical conditions — puts FraiseQL in the same performance tier as the fastest GraphQL frameworks available. The gap to the leader is within benchmark noise. Chasing that gap is not the point.

The point is where the complexity lives.


Source: VelocityBench 2026-02-21. Load tool: hey v0.1.5, 50 connections, 2,000 requests × 3 runs (median reported), PostgreSQL 15, localhost.

FrameworkQ1 — shallow listQ3 — 3-level nestedChange
go-gqlgen30,994 RPS37,047 RPS+20%
fraiseql29,672 RPS27,872 RPS−6%
async-graphql22,842 RPS9,562 RPS−58%
strawberry1,108 RPS708 RPS−36%

Q1 is a flat list query. Q3 is the N+1 stress test — users → posts → comments, three levels deep.

FraiseQL and go-gqlgen are within 5% on Q1. On Q3, go-gqlgen pulls ahead. async-graphql loses 58% of throughput under nesting despite hand-written DataLoaders. strawberry degrades across the board.

FrameworkQ1 p99Q3 p99
fraiseql5.6 ms5.9 ms
go-gqlgen20.6 ms3.7 ms
async-graphql16.0 ms10.0 ms
strawberry91.5 ms115.3 ms

FraiseQL’s p99 barely moves between query depths: 5.6 ms → 5.9 ms. This matters for SLA budgets — query depth does not blow your tail latency.

FraiseQL: 16 MB RSS after a full load test. go-gqlgen: 41 MB. strawberry: 52 MB.

Source: VelocityBench 2026-02-22, sequential run to isolate per-framework throughput (40 workers, localhost).

FrameworkQ1 RPS
gin-rest5,850
fraiseql (cache off)5,545
actix-web-rest5,501
go-gqlgen5,019
fraiseql (cache on, rc.3)2,258
strawberry906

The 5% throughput gap between FraiseQL and go-gqlgen is real. In production — behind a load balancer, with a connection pool, on queries shaped to your actual workload — it is not measurable. Both frameworks are fast enough that the database becomes the bottleneck long before the framework does.

What the benchmark cannot capture is what you had to build to get there.

go-gqlgen generates a schema-first Go skeleton and gives you a fast foundation. You then write DataLoaders, one per relation, to protect against N+1. You wire them into context middleware. You test them. You update them when the schema changes. The framework is fast because it gets out of the way — and that means the complexity is yours to carry.

FraiseQL resolves N+1 at the database level, before the application sees the query. A SQL view pre-composes the nested JSONB structure. The framework executes one SELECT data FROM v_post regardless of how deep the GraphQL query goes. There are no DataLoaders to write or maintain.

-- v_post.sql
-- This IS the resolver. One view. One query at runtime. No DataLoader.
CREATE OR REPLACE VIEW v_post AS
SELECT
p.id,
jsonb_build_object(
'id', p.id,
'title', p.title,
'content', p.content,
'author', jsonb_build_object(
'id', u.id,
'username', u.identifier
),
'comments', COALESCE(
jsonb_agg(
jsonb_build_object('id', c.id, 'content', c.content)
ORDER BY c.created_at
) FILTER (WHERE c.id IS NOT NULL),
'[]'
)
) AS data
FROM tb_post p
JOIN tb_user u ON u.pk_user = p.fk_user
LEFT JOIN tb_comment c ON c.fk_post = p.pk_post
GROUP BY p.pk_post, u.pk_user;

A DBA can read this, run EXPLAIN ANALYZE on it, add an index, and redeploy — without touching application code.

Both approaches work. Both are fast. The question is where you want the complexity: in a SQL file that the database can explain, or in application code that only your compiler can verify.


REST uses the same JSON-shaped views as GraphQL — expect comparable throughput (same DB work, thin HTTP translation layer).

gRPC uses row-shaped views that skip PostgreSQL’s json_agg serialization. In synthetic benchmarks this yields measurably lower DB CPU. In production the difference depends on query complexity and DB load.

Transport suite benchmarks are tracked in VelocityBench. This section will be updated with measured data when results are published.


All numbers on this page come from the VelocityBench public reports. Clone the repo and run make bench to reproduce them on your own hardware.

Terminal window
git clone https://github.com/fraiseql/velocitybench
cd velocitybench
make bench FRAMEWORK=fraiseql