← Extractions

Optimizing Rails apps with a GraphQL layer (Caio Almeida, wroclove.rb 2024)

Caio Almeida from Meedan shares eight years of hard-won lessons running a Rails + GraphQL monolith (the Check fact-checking platform). He walks through performance testing, monitoring at HTTP/query/field levels, N+1 solutions (graphql-batch, graphql-preload, look-ahead), safeguards (max depth, timeout), caching (graphql-ruby-fragment-cache, event-based cached fields), query batching via multiplex, and Q&A on authorization and whether to go back to REST.

Model
claude-opus-4-7
Ingestion
3f33be13
Input tokens
110,123
fresh
41,671
cached
55,428
cache write
13,024
Output tokens
11,701
Duration
167.5s
Roundtrips
4
Tool calls
10
Cost
$0.00
Nodes/edges extracted
34 / 54
Read set (nodes/edges)
68 / 2

Nodes (34)

create Sentry tool
kind (empty) → tool
name (empty) → Sentry
slug (empty) → sentry
attrs (empty) → {"category" => "service"}
description (empty) → Error-tracking service Meedan integrates with their Rails app. A graphql-ruby timeout handler calls Sentry.notify whe...
short_description (empty) → Error tracking and alerting service.
create PagerDuty tool
kind (empty) → tool
name (empty) → PagerDuty
slug (empty) → pagerduty
attrs (empty) → {"category" => "service"}
description (empty) → On-call alerting service triggered by uptime incidents (e.g. when an HTTP request exceeds a latency threshold) so tha...
short_description (empty) → On-call incident alerting service.
create Relay tool
kind (empty) → tool
name (empty) → Relay
slug (empty) → relay
attrs (empty) → {"category" => "library"}
description (empty) → Facebook's GraphQL client for React. Meedan's Check front-end uses React + Relay; the Relay network layer can be twea...
short_description (empty) → React GraphQL client with declarative data-fetching.
update Caio Almeida person
attrs (empty) → {"country" => "Brazil", "rails_since" => "2018"}
description Conference speaker. → Brazilian software engineer based in Brazil, working with Rails since 2018. Joined Meedan in 2016 as a software engin...
short_description Conference speaker. → Brazilian software engineer at Meedan, Rails/GraphQL practitioner.
create Meedan company
kind (empty) → company
name (empty) → Meedan
slug (empty) → meedan
attrs (empty) → {"industry" => "nonprofit / fact-checking tools", "headquarters" => "San Francisco"}
description (empty) → Nonprofit based in San Francisco that develops tools for collaborative fact-checking. Its main product, Check, was fu...
short_description (empty) → San Francisco-based nonprofit building collaborative fact-checking tools.
create Check project
kind (empty) → project
name (empty) → Check
slug (empty) → check
attrs (empty) → {"status" => "active", "license" => "open-source", "architecture" => "microservices, headless Rails GraphQL API"}
description (empty) → Meedan's main product: an open-source platform for fact-checking organizations around the world to track and verify m...
short_description (empty) → Meedan's open-source collaborative fact-checking platform.
create AWS CloudWatch tool
kind (empty) → tool
name (empty) → AWS CloudWatch
slug (empty) → aws-cloudwatch
attrs (empty) → {"category" => "service"}
description (empty) → AWS logging service where Meedan collects Rails HTTP request logs. Useful for total request duration but not for pinp...
short_description (empty) → AWS logging and metrics service.
update Optimizing performance in Rails apps with GraphQL layer talk
description Talk at wroclove.rb 2024. → Conference talk at wroclove.rb 2024 by Caio Almeida of Meedan, sharing eight years of lessons building and operating ...
short_description Talk at wroclove.rb 2024. → Caio Almeida's wroclove.rb 2024 talk on performance patterns for Rails + GraphQL.
update wroclove.rb 2024 event
No changes recorded.
update GraphQL tool
description API query language cited as having use cases where JSON API 'basically sucks'. Panel advice: be open-minded and pick ... → Query language describing data using a type system, with bindings for many programming languages. Open-sourced by Fac...
create graphql-ruby tool
kind (empty) → tool
name (empty) → graphql-ruby
slug (empty) → graphql-ruby
attrs (empty) → {"category" => "library", "language" => "Ruby"}
description (empty) → The canonical Ruby implementation of GraphQL. Early versions used DSL-style definers that were hard to write and reus...
short_description (empty) → Ruby gem implementing the GraphQL specification for Ruby/Rails apps.
create graphql-batch tool
kind (empty) → tool
name (empty) → graphql-batch
slug (empty) → graphql-batch
attrs (empty) → {"category" => "library", "language" => "Ruby"}
description (empty) → Ruby gem originally implemented by Shopify that batches data loading in graphql-ruby resolvers. Using a RecordLoader ...
short_description (empty) → Shopify gem for batch-loading associations in GraphQL resolvers.
create graphql-preload tool
kind (empty) → tool
name (empty) → graphql-preload
slug (empty) → graphql-preload
attrs (empty) → {"category" => "library", "language" => "Ruby"}
description (empty) → Ruby gem used to preload has_many associations (e.g. a post's tags) at the beginning of a GraphQL query scope, avoidi...
short_description (empty) → Ruby gem that eager-loads has_many associations in GraphQL resolvers.
create graphql-ruby-fragment-cache tool
kind (empty) → tool
name (empty) → graphql-ruby-fragment-cache
slug (empty) → graphql-ruby-fragment-cache
attrs (empty) → {"category" => "library", "language" => "Ruby"}
description (empty) → Ruby gem that caches fragments (individual fields) at the GraphQL API layer in graphql-ruby. Fields declare cache_fra...
short_description (empty) → Gem for caching individual fields at the GraphQL API layer.
create Honeycomb tool
kind (empty) → tool
name (empty) → Honeycomb
slug (empty) → honeycomb
attrs (empty) → {"category" => "service"}
description (empty) → Observability tool used at Meedan to trace GraphQL requests via OpenTelemetry. Gives per-request spans for parsing, v...
short_description (empty) → Observability SaaS built around OpenTelemetry tracing.
create OpenTelemetry tool
kind (empty) → tool
name (empty) → OpenTelemetry
slug (empty) → opentelemetry
attrs (empty) → {"category" => "platform"}
description (empty) → Open observability standard that instruments applications with spans and metrics. Used under the hood by Honeycomb to...
short_description (empty) → Vendor-neutral standard for distributed tracing and metrics.
create Apollo GraphQL tool
kind (empty) → tool
name (empty) → Apollo GraphQL
slug (empty) → apollo-graphql
attrs (empty) → {"category" => "service"}
description (empty) → GraphQL platform used by Meedan for schema visualization (acting as living documentation and schema-change tracking) ...
short_description (empty) → GraphQL platform offering schema visualization, monitoring and client tooling.
update Pundit tool
description Popular Ruby authorization gem; used in Adrian's talk as the example runtime dependency declared in an engine's gemsp... → Popular Ruby authorization gem. Meedan adopted Pundit when they first built Check with GraphQL, because graphql-ruby ...
short_description Minimal authorization Ruby gem using policy classes. → Ruby gem for object-level authorization policies.
update N+1 Queries concept
description Common ORM query-per-row performance problem. Sergyenko lists it as a core thing Ruby engineers working with data mus... → Common ORM performance problem where the number of database queries is proportional to the number of rows loaded. In ...
create Nested GraphQL query bottleneck concept
kind (empty) → concept
name (empty) → Nested GraphQL query bottleneck
slug (empty) → nested-graphql-query-bottleneck
attrs (empty) → {"category" => "pattern"}
description (empty) → Concept discussed in the talk: because GraphQL is highly expressive, clients can issue deeply nested queries (and eve...
short_description (empty) → Deeply nested GraphQL queries hiding expensive or circular data fetches.
create GraphQL look_ahead concept
kind (empty) → concept
name (empty) → GraphQL look_ahead
slug (empty) → graphql-look_ahead
attrs (empty) → {"category" => "pattern"}
description (empty) → graphql-ruby feature where a field receives a look_ahead object describing the tree of fields the caller requested. R...
short_description (empty) → graphql-ruby feature exposing the requested query tree to resolvers.
create GraphQL max_depth concept
kind (empty) → concept
name (empty) → GraphQL max_depth
slug (empty) → graphql-max_depth
attrs (empty) → {"category" => "practice"}
description (empty) → A graphql-ruby schema option that rejects queries nested beyond a configured depth (e.g. 4). Simple safeguard against...
short_description (empty) → Schema-level limit on nesting depth of incoming GraphQL queries.
create GraphQL query timeout concept
kind (empty) → concept
name (empty) → GraphQL query timeout
slug (empty) → graphql-query-timeout
attrs (empty) → {"category" => "practice"}
description (empty) → Control added to a graphql-ruby schema that caps the total execution time of a GraphQL query. When exceeded, the hand...
short_description (empty) → Per-query maximum execution time enforced at the GraphQL schema level.
create GraphQL query batching concept
kind (empty) → concept
name (empty) → GraphQL query batching
slug (empty) → graphql-query-batching
attrs (empty) → {"category" => "pattern"}
description (empty) → Pattern where a GraphQL client (Apollo's client-side batching, or React Relay's network layer) combines queries trigg...
short_description (empty) → Combining multiple GraphQL queries into one HTTP request and executing them concurrently.
create Event-based GraphQL field caching concept
kind (empty) → concept
name (empty) → Event-based GraphQL field caching
slug (empty) → event-based-graphql-field-caching
attrs (empty) → {"category" => "pattern"}
description (empty) → Caching approach Meedan built in-house: each expensive cached field declares a starting value and a list of model eve...
short_description (empty) → Explicit list of model events that invalidate a cached GraphQL field.
create GraphQL performance regression tests concept
kind (empty) → concept
name (empty) → GraphQL performance regression tests
slug (empty) → graphql-performance-regression-tests
attrs (empty) → {"category" => "practice"}
description (empty) → Practice of writing tests (e.g. Minitest assert_queries helper) that assert how many database queries a given GraphQL...
short_description (empty) → Minitest helpers asserting maximum database queries per GraphQL operation.
create Premature optimization concept
kind (empty) → concept
name (empty) → Premature optimization
slug (empty) → premature-optimization
attrs (empty) → {"category" => "practice"}
description (empty) → Well-known computer-science adage cited as the 'root of all evil'. In the talk used to temper optimization advice: an...
short_description (empty) → Classic warning that optimizing too early wastes effort on the wrong code.
create Monitoring is the most important optimization habit takeaway
kind (empty) → takeaway
name (empty) → Monitoring is the most important optimization habit
slug (empty) → monitoring-is-the-most-important-optimization-habit
attrs (empty) → {"type" => "recommendation"}
description (empty) → Speaker's single most-emphasized takeaway: you can't improve what you don't measure. Set up monitoring at multiple le...
short_description (empty) → Without layered monitoring you can't identify real GraphQL bottlenecks.
create Make performance a team mindset takeaway
kind (empty) → takeaway
name (empty) → Make performance a team mindset
slug (empty) → make-performance-a-team-mindset
attrs (empty) → {"type" => "recommendation"}
description (empty) → Performance is an ongoing process, not a one-off sprint. For sustained adoption of monitoring and optimization tools,...
short_description (empty) → Optimization must be continuous and owned by the whole engineering team.
create Always evaluate trade-offs of GraphQL optimizations takeaway
kind (empty) → takeaway
name (empty) → Always evaluate trade-offs of GraphQL optimizations
slug (empty) → always-evaluate-trade-offs-of-graphql-optimizations
attrs (empty) → {"type" => "insight"}
description (empty) → Every GraphQL optimization (extra gems, look_ahead resolvers, custom caching DSLs) adds dependencies, learning curve ...
short_description (empty) → Performance wins like look_ahead can cost readability and onboarding time.
create Delay mutations to background jobs takeaway
kind (empty) → takeaway
name (empty) → Delay mutations to background jobs
slug (empty) → delay-mutations-to-background-jobs
attrs (empty) → {"type" => "recommendation"}
description (empty) → For GraphQL mutations with heavy side-effects — calls to external services, bulk operations like 'select all + tag' o...
short_description (empty) → Offload slow mutation work (external calls, bulk ops) to background jobs.
create Denormalization vs graphql-batch / graphql-preload question
kind (empty) → question
name (empty) → Denormalization vs graphql-batch / graphql-preload
slug (empty) → denormalization-vs-graphql-batch-graphql-preload
attrs (empty) → {"answer_summary" => "Didn't evaluate denormalization specifically; graphql-batch was the first fix, and because Chec...
description (empty) → Audience question asking whether the team evaluated data denormalization (e.g. adding a tags field directly on the Po...
short_description (empty) → Did you compare denormalizing fields versus using batch/preload gems?
create Authorization strategies in GraphQL question
kind (empty) → question
name (empty) → Authorization strategies in GraphQL
slug (empty) → authorization-strategies-in-graphql
attrs (empty) → {"answer_summary" => "Authenticate at the controller; authorize at type/field level using graphql-ruby + Pundit. Meed...
description (empty) → Audience question about authorization patterns in large GraphQL apps: field level vs layer level, how layers coordina...
short_description (empty) → How to handle authorization for flexible GraphQL queries?
create Have you considered going back to REST? question
kind (empty) → question
name (empty) → Have you considered going back to REST?
slug (empty) → have-you-considered-going-back-to-rest
attrs (empty) → {"answer_summary" => "No. Check is open-source with three in-house clients and many external fact-checking agencies —...
description (empty) → Audience question at the end of the talk. Speaker jokes he 'scratches himself every day' but no: Check is open-source...
short_description (empty) → Would you drop GraphQL and return to REST APIs?

Edges (54)

update Caio Almeida → authored → Optimizing performance in Rails apps with GraphQL layer
context (empty) → Delivered the talk at wroclove.rb 2024.
update Optimizing performance in Rails apps with GraphQL layer → presented_at → wroclove.rb 2024
context (empty) → Talk given at wroclove.rb 2024 (originally scheduled for 2020 before pandemic cancellation).
create Caio Almeida → attended → wroclove.rb 2024
context (empty) → Speaker at the conference.
relation (empty) → attended
source_node_id (empty) → 8e94e35e-1e33-48c7-ac3e-b72e4e1c8c9e
target_node_id (empty) → 748e0524-a102-41d4-97dc-575881583d91
create Caio Almeida → works_at → Meedan
attrs (empty) → {"role" => "software engineer", "since" => "2016"}
context (empty) → Software engineer at Meedan since 2016.
relation (empty) → works_at
source_node_id (empty) → 8e94e35e-1e33-48c7-ac3e-b72e4e1c8c9e
target_node_id (empty) → cc6d7a67-eef0-4196-9a7e-0874b4868ece
create Caio Almeida → works_on → Check
attrs (empty) → {"role" => "lead engineer of PHP→Rails rewrite"}
context (empty) → Led migration of Meedan's main product Check from PHP to Rails.
relation (empty) → works_on
source_node_id (empty) → 8e94e35e-1e33-48c7-ac3e-b72e4e1c8c9e
target_node_id (empty) → 8b4e5d9c-9987-43bb-b7bd-3c9f2fc5af4a
create Check → uses → GraphQL
context (empty) → Check's core Rails API is a headless GraphQL API.
relation (empty) → uses
source_node_id (empty) → 8b4e5d9c-9987-43bb-b7bd-3c9f2fc5af4a
target_node_id (empty) → c6a1041c-3116-4194-b7f0-eba7cd4a7e64
create Check → uses → graphql-ruby
context (empty) → Ruby implementation of GraphQL powering Check's API.
relation (empty) → uses
source_node_id (empty) → 8b4e5d9c-9987-43bb-b7bd-3c9f2fc5af4a
target_node_id (empty) → be81c4e9-2645-4f1d-90cc-0d6cfe93cb6c
create Check → uses → graphql-batch
context (empty) → Used to batch-load belongs_to associations and avoid N+1 queries.
relation (empty) → uses
source_node_id (empty) → 8b4e5d9c-9987-43bb-b7bd-3c9f2fc5af4a
target_node_id (empty) → f3af2e65-d82f-4f24-81e2-ac1f84dd0b2b
create Check → uses → Relay
context (empty) → Check's React front-end uses Relay with query batching in the network layer.
relation (empty) → uses
source_node_id (empty) → 8b4e5d9c-9987-43bb-b7bd-3c9f2fc5af4a
target_node_id (empty) → 204d8f3f-4978-4072-ac57-92411341cca4
create Check → uses → Honeycomb
context (empty) → Monitoring GraphQL query execution via OpenTelemetry spans.
relation (empty) → uses
source_node_id (empty) → 8b4e5d9c-9987-43bb-b7bd-3c9f2fc5af4a
target_node_id (empty) → 9fe05a75-6726-4be8-b578-0058603267a6
create Check → uses → OpenTelemetry
context (empty) → Instrumentation underlying Honeycomb tracing.
relation (empty) → uses
source_node_id (empty) → 8b4e5d9c-9987-43bb-b7bd-3c9f2fc5af4a
target_node_id (empty) → 39ce1c2f-63e7-4a8d-859f-40e7f1bd6d4b
create Check → uses → Apollo GraphQL
context (empty) → Schema visualization, per-field monitoring, and Slack daily summaries of slow queries.
relation (empty) → uses
source_node_id (empty) → 8b4e5d9c-9987-43bb-b7bd-3c9f2fc5af4a
target_node_id (empty) → cebd5aab-3634-4afe-b0a8-ba8fb96ddffc
create Check → uses → AWS CloudWatch
context (empty) → Collects Rails HTTP request logs.
relation (empty) → uses
source_node_id (empty) → 8b4e5d9c-9987-43bb-b7bd-3c9f2fc5af4a
target_node_id (empty) → a2a3a19e-767f-42a8-8776-c2fcf62c6397
create Check → uses → Sentry
context (empty) → Receives notifications when GraphQL queries exceed timeout.
relation (empty) → uses
source_node_id (empty) → 8b4e5d9c-9987-43bb-b7bd-3c9f2fc5af4a
target_node_id (empty) → 9b81df6c-7817-4cd8-91a1-bfeefb7fbce8
create Check → uses → PagerDuty
context (empty) → Triggers on-call incidents from uptime alerts.
relation (empty) → uses
source_node_id (empty) → 8b4e5d9c-9987-43bb-b7bd-3c9f2fc5af4a
target_node_id (empty) → fefd3a9e-5cec-4b86-8ba8-cb49dc16f4cd
create Check → uses → Pundit
context (empty) → Authorization enforced below GraphQL because graphql-ruby didn't offer it at the API layer when Check adopted GraphQL.
relation (empty) → uses
source_node_id (empty) → 8b4e5d9c-9987-43bb-b7bd-3c9f2fc5af4a
target_node_id (empty) → 1ebb50fc-98ba-48a0-8720-cbf7138c2eed
create Meedan → works_on → Check
context (empty) → Check is Meedan's flagship product.
relation (empty) → works_on
source_node_id (empty) → cc6d7a67-eef0-4196-9a7e-0874b4868ece
target_node_id (empty) → 8b4e5d9c-9987-43bb-b7bd-3c9f2fc5af4a
create Optimizing performance in Rails apps with GraphQL layer → about → GraphQL
context (empty) → Talk focuses on Rails applications with a GraphQL layer.
relation (empty) → about
source_node_id (empty) → c6952b14-5193-4339-8f6a-9ebc6f3cd440
target_node_id (empty) → c6a1041c-3116-4194-b7f0-eba7cd4a7e64
create Optimizing performance in Rails apps with GraphQL layer → about → graphql-ruby
context (empty) → Uses graphql-ruby features (types, connections, look_ahead, max_depth, multiplex, timeouts, authorization).
relation (empty) → about
source_node_id (empty) → c6952b14-5193-4339-8f6a-9ebc6f3cd440
target_node_id (empty) → be81c4e9-2645-4f1d-90cc-0d6cfe93cb6c
create Optimizing performance in Rails apps with GraphQL layer → about → N+1 Queries
context (empty) → N+1 is framed as the classic GraphQL performance problem.
relation (empty) → about
source_node_id (empty) → c6952b14-5193-4339-8f6a-9ebc6f3cd440
target_node_id (empty) → ee033151-443a-4285-aa68-fbc2e9755d06
create Optimizing performance in Rails apps with GraphQL layer → about → graphql-batch
context (empty) → Presented as the Shopify-built solution for batching belongs_to loads.
relation (empty) → about
source_node_id (empty) → c6952b14-5193-4339-8f6a-9ebc6f3cd440
target_node_id (empty) → f3af2e65-d82f-4f24-81e2-ac1f84dd0b2b
create Optimizing performance in Rails apps with GraphQL layer → about → graphql-preload
context (empty) → Presented as the solution for preloading has_many associations.
relation (empty) → about
source_node_id (empty) → c6952b14-5193-4339-8f6a-9ebc6f3cd440
target_node_id (empty) → 953a145f-a42f-477e-b099-618314e0574b
create Optimizing performance in Rails apps with GraphQL layer → about → GraphQL look_ahead
context (empty) → Explains predictive preloading via look_ahead for complex nested queries.
relation (empty) → about
source_node_id (empty) → c6952b14-5193-4339-8f6a-9ebc6f3cd440
target_node_id (empty) → 7dc62afe-5967-4d13-be8e-208ed0b34e39
create Optimizing performance in Rails apps with GraphQL layer → about → GraphQL max_depth
context (empty) → Shown as a simple safeguard against deep nested queries.
relation (empty) → about
source_node_id (empty) → c6952b14-5193-4339-8f6a-9ebc6f3cd440
target_node_id (empty) → c1fc40a4-acdf-4448-9404-7723b9b4ea6b
create Optimizing performance in Rails apps with GraphQL layer → about → GraphQL query timeout
context (empty) → Shown as a control over whole-query execution time integrated with Sentry.
relation (empty) → about
source_node_id (empty) → c6952b14-5193-4339-8f6a-9ebc6f3cd440
target_node_id (empty) → dae7ca29-db2f-4fcb-81eb-8a2fafdaf74d
create Optimizing performance in Rails apps with GraphQL layer → about → graphql-ruby-fragment-cache
context (empty) → Demonstrated as API-layer fragment caching for expensive fields.
relation (empty) → about
source_node_id (empty) → c6952b14-5193-4339-8f6a-9ebc6f3cd440
target_node_id (empty) → 9cedcb96-c456-4d53-958c-4d50c8cb3a73
create Optimizing performance in Rails apps with GraphQL layer → about → Event-based GraphQL field caching
context (empty) → Describes Meedan's own event-based cached-field library built on Ruby meta-programming and Rails low-level caching.
relation (empty) → about
source_node_id (empty) → c6952b14-5193-4339-8f6a-9ebc6f3cd440
target_node_id (empty) → 1c63e985-d968-4dcf-b1df-b81d8e95ae75
create Optimizing performance in Rails apps with GraphQL layer → about → GraphQL query batching
context (empty) → Covers Apollo/Relay client batching and graphql-ruby's multiplex on the server side.
relation (empty) → about
source_node_id (empty) → c6952b14-5193-4339-8f6a-9ebc6f3cd440
target_node_id (empty) → af9fb052-6275-447c-9689-4c6ad41c0772
create Optimizing performance in Rails apps with GraphQL layer → about → GraphQL performance regression tests
context (empty) → Shown as assert_queries-based Minitest helpers to prevent N+1 regressions.
relation (empty) → about
source_node_id (empty) → c6952b14-5193-4339-8f6a-9ebc6f3cd440
target_node_id (empty) → da77f6d8-91f0-429d-8103-27a13e6ba3de
create Optimizing performance in Rails apps with GraphQL layer → about → Nested GraphQL query bottleneck
context (empty) → Deep/unpredictable queries are a central problem the talk addresses.
relation (empty) → about
source_node_id (empty) → c6952b14-5193-4339-8f6a-9ebc6f3cd440
target_node_id (empty) → ff9b1251-f5b4-4b6d-9bc4-bada69c5c00a
create Optimizing performance in Rails apps with GraphQL layer → about → Premature optimization
context (empty) → Discusses the adage while arguing for anticipatory design where feasible.
relation (empty) → about
source_node_id (empty) → c6952b14-5193-4339-8f6a-9ebc6f3cd440
target_node_id (empty) → 5bd44190-5f0e-4459-884c-2879f0cb671f
create Optimizing performance in Rails apps with GraphQL layer → about → Honeycomb
context (empty) → Used in the monitoring-level examples.
relation (empty) → about
source_node_id (empty) → c6952b14-5193-4339-8f6a-9ebc6f3cd440
target_node_id (empty) → 9fe05a75-6726-4be8-b578-0058603267a6
create Optimizing performance in Rails apps with GraphQL layer → about → Apollo GraphQL
context (empty) → Showcased for schema visualization and per-field performance metrics.
relation (empty) → about
source_node_id (empty) → c6952b14-5193-4339-8f6a-9ebc6f3cd440
target_node_id (empty) → cebd5aab-3634-4afe-b0a8-ba8fb96ddffc
create Optimizing performance in Rails apps with GraphQL layer → about → OpenTelemetry
context (empty) → Underlying tracing standard powering Honeycomb instrumentation.
relation (empty) → about
source_node_id (empty) → c6952b14-5193-4339-8f6a-9ebc6f3cd440
target_node_id (empty) → 39ce1c2f-63e7-4a8d-859f-40e7f1bd6d4b
create Optimizing performance in Rails apps with GraphQL layer → about → Check
context (empty) → All concrete examples come from Meedan's Check application.
relation (empty) → about
source_node_id (empty) → c6952b14-5193-4339-8f6a-9ebc6f3cd440
target_node_id (empty) → 8b4e5d9c-9987-43bb-b7bd-3c9f2fc5af4a
create Monitoring is the most important optimization habit → from_talk → Optimizing performance in Rails apps with GraphQL layer
context (empty) → Speaker's headline takeaway.
relation (empty) → from_talk
source_node_id (empty) → c8ef0a42-aae4-4376-81a5-44935f58f680
target_node_id (empty) → c6952b14-5193-4339-8f6a-9ebc6f3cd440
create Make performance a team mindset → from_talk → Optimizing performance in Rails apps with GraphQL layer
context (empty) → Closing recommendation on sustained adoption.
relation (empty) → from_talk
source_node_id (empty) → 15d45371-3d02-4f9d-bdca-6fa04549f75d
target_node_id (empty) → c6952b14-5193-4339-8f6a-9ebc6f3cd440
create Always evaluate trade-offs of GraphQL optimizations → from_talk → Optimizing performance in Rails apps with GraphQL layer
context (empty) → Repeated caution throughout the talk.
relation (empty) → from_talk
source_node_id (empty) → 4f95efd5-0dcf-4b5c-b47e-1efaf45b60d6
target_node_id (empty) → c6952b14-5193-4339-8f6a-9ebc6f3cd440
create Delay mutations to background jobs → from_talk → Optimizing performance in Rails apps with GraphQL layer
context (empty) → Mutation-side recommendation near the end.
relation (empty) → from_talk
source_node_id (empty) → 7a8976ee-8174-4d74-bec9-61ca801397a3
target_node_id (empty) → c6952b14-5193-4339-8f6a-9ebc6f3cd440
create Denormalization vs graphql-batch / graphql-preload → asked_at → Optimizing performance in Rails apps with GraphQL layer
context (empty) → Q&A about alternative optimization approaches.
relation (empty) → asked_at
source_node_id (empty) → 2a03cf0c-0899-406f-956b-796791e214bc
target_node_id (empty) → c6952b14-5193-4339-8f6a-9ebc6f3cd440
create Authorization strategies in GraphQL → asked_at → Optimizing performance in Rails apps with GraphQL layer
context (empty) → Q&A about authorization for flexible GraphQL queries.
relation (empty) → asked_at
source_node_id (empty) → 7250db27-6403-484d-b712-864427195e72
target_node_id (empty) → c6952b14-5193-4339-8f6a-9ebc6f3cd440
create Have you considered going back to REST? → asked_at → Optimizing performance in Rails apps with GraphQL layer
context (empty) → Q&A asking if Meedan has considered reverting from GraphQL to REST.
relation (empty) → asked_at
source_node_id (empty) → f69d163c-ce42-4f07-a86a-fe675c2484d4
target_node_id (empty) → c6952b14-5193-4339-8f6a-9ebc6f3cd440
create Authorization strategies in GraphQL → about → Pundit
context (empty) → Pundit is cited as the authorization gem Meedan uses.
relation (empty) → about
source_node_id (empty) → 7250db27-6403-484d-b712-864427195e72
target_node_id (empty) → 1ebb50fc-98ba-48a0-8720-cbf7138c2eed
create Authorization strategies in GraphQL → about → graphql-ruby
context (empty) → graphql-ruby's field-level authorization and context object are the core of the answer.
relation (empty) → about
source_node_id (empty) → 7250db27-6403-484d-b712-864427195e72
target_node_id (empty) → be81c4e9-2645-4f1d-90cc-0d6cfe93cb6c
create Denormalization vs graphql-batch / graphql-preload → about → graphql-batch
context (empty) → Question compares denormalization with graphql-batch.
relation (empty) → about
source_node_id (empty) → 2a03cf0c-0899-406f-956b-796791e214bc
target_node_id (empty) → f3af2e65-d82f-4f24-81e2-ac1f84dd0b2b
create Denormalization vs graphql-batch / graphql-preload → about → graphql-preload
context (empty) → Question compares denormalization with graphql-preload.
relation (empty) → about
source_node_id (empty) → 2a03cf0c-0899-406f-956b-796791e214bc
target_node_id (empty) → 953a145f-a42f-477e-b099-618314e0574b
create Have you considered going back to REST? → about → GraphQL
context (empty) → About whether to abandon GraphQL.
relation (empty) → about
source_node_id (empty) → f69d163c-ce42-4f07-a86a-fe675c2484d4
target_node_id (empty) → c6a1041c-3116-4194-b7f0-eba7cd4a7e64
create Caio Almeida → has_skill → graphql-ruby
attrs (empty) → {"level" => "expert"}
context (empty) → Uses graphql-ruby extensively in production at Meedan.
relation (empty) → has_skill
source_node_id (empty) → 8e94e35e-1e33-48c7-ac3e-b72e4e1c8c9e
target_node_id (empty) → be81c4e9-2645-4f1d-90cc-0d6cfe93cb6c
create Caio Almeida → has_skill → GraphQL
attrs (empty) → {"level" => "expert"}
context (empty) → Eight years operating a Rails+GraphQL product.
relation (empty) → has_skill
source_node_id (empty) → 8e94e35e-1e33-48c7-ac3e-b72e4e1c8c9e
target_node_id (empty) → c6a1041c-3116-4194-b7f0-eba7cd4a7e64
create Caio Almeida → recommends → graphql-batch
context (empty) → First tool Meedan introduced to fix N+1 on belongs_to.
relation (empty) → recommends
source_node_id (empty) → 8e94e35e-1e33-48c7-ac3e-b72e4e1c8c9e
target_node_id (empty) → f3af2e65-d82f-4f24-81e2-ac1f84dd0b2b
create Caio Almeida → recommends → graphql-preload
context (empty) → Recommended for preloading has_many associations.
relation (empty) → recommends
source_node_id (empty) → 8e94e35e-1e33-48c7-ac3e-b72e4e1c8c9e
target_node_id (empty) → 953a145f-a42f-477e-b099-618314e0574b
create Caio Almeida → recommends → Honeycomb
context (empty) → Cited as successfully used for GraphQL tracing via OpenTelemetry.
relation (empty) → recommends
source_node_id (empty) → 8e94e35e-1e33-48c7-ac3e-b72e4e1c8c9e
target_node_id (empty) → 9fe05a75-6726-4be8-b578-0058603267a6
create Caio Almeida → recommends → Apollo GraphQL
context (empty) → Highlighted for per-field metrics and schema documentation.
relation (empty) → recommends
source_node_id (empty) → 8e94e35e-1e33-48c7-ac3e-b72e4e1c8c9e
target_node_id (empty) → cebd5aab-3634-4afe-b0a8-ba8fb96ddffc
create Caio Almeida → recommends → GraphQL performance regression tests
context (empty) → Advocates assert_queries-based tests to catch N+1 before production.
relation (empty) → recommends
source_node_id (empty) → 8e94e35e-1e33-48c7-ac3e-b72e4e1c8c9e
target_node_id (empty) → da77f6d8-91f0-429d-8103-27a13e6ba3de

Read set

68 nodes

talk Optimizing performance in Rails apps with GraphQL layer search_nodes+get_node_edges talk Better WebPerformance with Rails search_nodes talk LATERAL Joins Rails Performance Lightning Talk search_nodes concept RAIL Performance Model search_nodes tool ViewComponent search_nodes concept Performance Time Budget search_nodes resource The Rails and Hotwire Codex search_nodes talk Sonic Pi Music Performance search_nodes concept Static Page Caching via nginx search_nodes tool GraphQL search_nodes takeaway Name Things To Find Their Properties search_nodes concept Retrieval Augmented Generation search_nodes concept AI Agent search_nodes project Ruby News search_nodes talk Events events events search_nodes tool ChatGPT search_nodes tool langchainrb search_nodes tool SXG Validator search_nodes concept xkcd Dependency / Nebraska Problem search_nodes concept Vector Database search_nodes tool RealtimeBoard search_nodes tool Midjourney search_nodes takeaway Be kind and build useful things search_nodes resource awesome-ddd search_nodes project Nerds and Threads search_nodes event wroclove.rb 2024 search_nodes event wroclove.rb 2022 search_nodes event wroclove.rb 2023 search_nodes event wroclove.rb 2025 search_nodes event wroclove.rb 2026 search_nodes event wroclove.rb 2019 search_nodes event wroclove.rb 2018 search_nodes talk Mutation testing workshop wroclove.rb 2019 search_nodes talk Webmock unmocked search_nodes talk One machine please, make it Turing search_nodes concept N+1 Queries search_nodes question Aren't query optimizations a better first step than caching? search_nodes concept Flat Query Structure search_nodes takeaway Prefer LATERAL over CTE for filtered top-N per group search_nodes takeaway Read models must not depend on each other search_nodes question Should touch on belongs_to be avoided in complex apps? search_nodes takeaway Use Immediate Transactions for Rails search_nodes concept destroy_all vs delete_all search_nodes concept LATERAL join search_nodes person Caio Almeida search_nodes project Ruby Romania search_nodes concept DNS geolocation routing search_nodes person Adam Okoń search_nodes tool Prometheus search_nodes resource Rocket Real-Time Benchmark search_nodes tool Datadog search_nodes tool Grafana search_nodes tool New Relic search_nodes tool Codecov search_nodes takeaway Sign serverlessforruby.org petition search_nodes takeaway Trailblazer tracing saves thousands of debugging hours search_nodes concept Distributed Monolith search_nodes takeaway Graph resolvers compute minimal API calls automatically search_nodes tool Falcor search_nodes tool Pathom search_nodes question JSON API or GraphQL — what do you recommend? search_nodes project AnyCable search_nodes concept GitHub Self-Hosted Runner search_nodes takeaway Contribute to Arkency aggregates repository search_nodes tool Ruby search_nodes tool JSON API Resources search_nodes project granite search_nodes tool Representable search_nodes

2 edges