Which API design pattern is right for my project?
Decision tree
Determine the right API design style for your integration scenario.
Overview
Full decision path
Start: Q1
Q1 — Who are the primary consumers of this API?
- A: Internal services (backend-to-backend) → next question Q2 — Is low-latency real-time streaming required?
- B: Third-party developers / public → next question Q2 — Is low-latency real-time streaming required?
- C: Mobile or browser clients → next question Q3 — Does the client need fine-grained control over exactly which fields are fetched?
Q2 — Is low-latency real-time streaming required?
- yes → next question Q4 — Is bidirectional communication (client push AND server push) needed?
- no → next question Q5 — Is strict contract-first API design with generated SDKs a priority?
Q3 — Does the client need fine-grained control over exactly which fields are fetched?
- yes → outcome GraphQL
- no → next question Q5 — Is strict contract-first API design with generated SDKs a priority?
Q4 — Is bidirectional communication (client push AND server push) needed?
- yes → outcome WebSocket / Server-Sent Events
- no → outcome gRPC / Protocol Buffers
Q5 — Is strict contract-first API design with generated SDKs a priority?
- yes → outcome REST + OpenAPI
- no → outcome REST (pragmatic)
Outcomes
- REST (pragmatic)
(OUT_REST) - Reached from Q5 (no).
- REST + OpenAPI
(OUT_REST_OPENAPI) - Reached from Q5 (yes).
- GraphQL
(OUT_GRAPHQL) - Reached from Q3 (yes).
- gRPC / Protocol Buffers
(OUT_GRPC) - Reached from Q4 (no).
- WebSocket / Server-Sent Events
(OUT_WEBSOCKET) - Reached from Q4 (yes).
Machine-Readable JSON (Canonical Model)
View JSON
{
"_meta": {
"schema": "https://www.drawdecisiontree.com/decision-dag.schema.json",
"source": "https://www.drawdecisiontree.com",
"description": "DrawDecisionTree.com is a free tool for building, sharing, and embedding interactive decision trees. This file is the machine-readable export of a published decision tree. The `dsl` field contains the original source in the Decision DAG DSL; the `dag` schema is documented at the URL in `schema` above.",
"links": {
"interactive": "https://www.drawdecisiontree.com/trees/drawdecisiontree/api-design",
"embed": "https://www.drawdecisiontree.com/embed/path/drawdecisiontree/api-design",
"dsl_reference": "https://www.drawdecisiontree.com/decision-tree-dsl-reference",
"guides": "https://www.drawdecisiontree.com/guides",
"schema_docs": "https://www.drawdecisiontree.com/decision-dag.schema.json",
"author_trees": "https://www.drawdecisiontree.com/trees/drawdecisiontree"
},
"generated_at": "2026-07-03T21:08:41.896Z"
},
"author": {
"handle": "drawdecisiontree",
"first_name": "Andrew",
"last_name": null,
"avatar_url": "1d32d828-b6ca-40ec-bdd7-771fe7b9c36a/avatar-1778531481027.svg",
"display_name": "Andrew"
},
"file": {
"id": "6e71ec38-b9fc-4110-b102-4e2a40a7e6fa",
"name": "Which API design pattern is right for my project?",
"public_slug": "api-design",
"updated_at": "2026-05-12T16:53:43.587978+00:00",
"url": "https://www.drawdecisiontree.com/trees/drawdecisiontree/api-design",
"json_url": "https://www.drawdecisiontree.com/trees/drawdecisiontree/api-design/tree.json",
"dsl_url": "https://www.drawdecisiontree.com/trees/drawdecisiontree/api-design/tree.dag"
},
"meta": {
"description": "Determine the right API design style for your integration scenario.",
"mode": "decision",
"entry": "Q1",
"tags": [],
"image": null
},
"questions": [
{
"id": "Q1",
"text": "Who are the primary consumers of this API?"
},
{
"id": "Q2",
"text": "Is low-latency real-time streaming required?"
},
{
"id": "Q3",
"text": "Does the client need fine-grained control over exactly which fields are fetched?"
},
{
"id": "Q4",
"text": "Is bidirectional communication (client push AND server push) needed?"
},
{
"id": "Q5",
"text": "Is strict contract-first API design with generated SDKs a priority?"
}
],
"outcomes": [
{
"id": "OUT_REST",
"label": "REST (pragmatic)"
},
{
"id": "OUT_REST_OPENAPI",
"label": "REST + OpenAPI"
},
{
"id": "OUT_GRAPHQL",
"label": "GraphQL"
},
{
"id": "OUT_GRPC",
"label": "gRPC / Protocol Buffers"
},
{
"id": "OUT_WEBSOCKET",
"label": "WebSocket / Server-Sent Events"
}
],
"dsl": "dag: Which API design pattern is right for my project?\nversion: 1.0.0\ndescription: Determine the right API design style for your integration scenario.\nentry: Q1\n\nQ1: Who are the primary consumers of this API?\n A: Internal services (backend-to-backend) -> Q2\n B: Third-party developers / public -> Q2\n C: Mobile or browser clients -> Q3\n\nQ2: Is low-latency real-time streaming required?\n yes -> Q4\n no -> Q5\n\nQ3: Does the client need fine-grained control over exactly which fields are fetched?\n yes -> [OUT_GRAPHQL]\n no -> Q5\n\nQ4: Is bidirectional communication (client push AND server push) needed?\n yes -> [OUT_WEBSOCKET]\n no -> [OUT_GRPC]\n\nQ5: Is strict contract-first API design with generated SDKs a priority?\n yes -> [OUT_REST_OPENAPI]\n no -> [OUT_REST]\n\n[OUT_REST]: REST (pragmatic)\n description: Standard HTTP verbs and JSON payloads. Best default choice for most CRUD-style service integrations.\n code: API_REST\n\n[OUT_REST_OPENAPI]: REST + OpenAPI\n description: REST with an OpenAPI 3.x spec-first workflow. Enables auto-generated SDKs, mocks, and documentation for public or partner APIs.\n code: API_REST_OPENAPI\n\n[OUT_GRAPHQL]: GraphQL\n description: Flexible query language allowing clients to request exactly the data they need. Ideal for complex, rapidly evolving frontend data requirements.\n code: API_GRAPHQL\n\n[OUT_GRPC]: gRPC / Protocol Buffers\n description: High-performance binary RPC with strongly typed contracts. Best for internal microservice communication where throughput and latency matter.\n code: API_GRPC\n\n[OUT_WEBSOCKET]: WebSocket / Server-Sent Events\n description: Full-duplex or server-push protocol. Use for chat, live dashboards, collaborative editing, or any scenario requiring real-time bidirectional messaging.\n code: API_WEBSOCKET\n\nroutes:\n Q1=A, Q2=no, Q5=no -> [OUT_REST]\n Q1=A, Q2=no, Q5=yes -> [OUT_REST_OPENAPI]\n Q1=A, Q2=yes, Q4=no -> [OUT_GRPC]\n Q1=A, Q2=yes, Q4=yes -> [OUT_WEBSOCKET]\n Q1=B, Q2=no, Q5=no -> [OUT_REST]\n Q1=B, Q2=no, Q5=yes -> [OUT_REST_OPENAPI]\n Q1=B, Q2=yes, Q4=no -> [OUT_GRPC]\n Q1=B, Q2=yes, Q4=yes -> [OUT_WEBSOCKET]\n Q1=C, Q3=yes -> [OUT_GRAPHQL]\n Q1=C, Q3=no, Q5=no -> [OUT_REST]\n Q1=C, Q3=no, Q5=yes -> [OUT_REST_OPENAPI]\n"
}DSL Representation
dag: Which API design pattern is right for my project?
version: 1.0.0
description: Determine the right API design style for your integration scenario.
entry: Q1
Q1: Who are the primary consumers of this API?
A: Internal services (backend-to-backend) -> Q2
B: Third-party developers / public -> Q2
C: Mobile or browser clients -> Q3
Q2: Is low-latency real-time streaming required?
yes -> Q4
no -> Q5
Q3: Does the client need fine-grained control over exactly which fields are fetched?
yes -> [OUT_GRAPHQL]
no -> Q5
Q4: Is bidirectional communication (client push AND server push) needed?
yes -> [OUT_WEBSOCKET]
no -> [OUT_GRPC]
Q5: Is strict contract-first API design with generated SDKs a priority?
yes -> [OUT_REST_OPENAPI]
no -> [OUT_REST]
[OUT_REST]: REST (pragmatic)
description: Standard HTTP verbs and JSON payloads. Best default choice for most CRUD-style service integrations.
code: API_REST
[OUT_REST_OPENAPI]: REST + OpenAPI
description: REST with an OpenAPI 3.x spec-first workflow. Enables auto-generated SDKs, mocks, and documentation for public or partner APIs.
code: API_REST_OPENAPI
[OUT_GRAPHQL]: GraphQL
description: Flexible query language allowing clients to request exactly the data they need. Ideal for complex, rapidly evolving frontend data requirements.
code: API_GRAPHQL
[OUT_GRPC]: gRPC / Protocol Buffers
description: High-performance binary RPC with strongly typed contracts. Best for internal microservice communication where throughput and latency matter.
code: API_GRPC
[OUT_WEBSOCKET]: WebSocket / Server-Sent Events
description: Full-duplex or server-push protocol. Use for chat, live dashboards, collaborative editing, or any scenario requiring real-time bidirectional messaging.
code: API_WEBSOCKET
routes:
Q1=A, Q2=no, Q5=no -> [OUT_REST]
Q1=A, Q2=no, Q5=yes -> [OUT_REST_OPENAPI]
Q1=A, Q2=yes, Q4=no -> [OUT_GRPC]
Q1=A, Q2=yes, Q4=yes -> [OUT_WEBSOCKET]
Q1=B, Q2=no, Q5=no -> [OUT_REST]
Q1=B, Q2=no, Q5=yes -> [OUT_REST_OPENAPI]
Q1=B, Q2=yes, Q4=no -> [OUT_GRPC]
Q1=B, Q2=yes, Q4=yes -> [OUT_WEBSOCKET]
Q1=C, Q3=yes -> [OUT_GRAPHQL]
Q1=C, Q3=no, Q5=no -> [OUT_REST]
Q1=C, Q3=no, Q5=yes -> [OUT_REST_OPENAPI]
Machine Access
- Static JSON:
/trees/drawdecisiontree/api-design/tree.json - Live JSON (SPA):
/json/drawdecisiontree/api-design - Raw DSL:
/trees/drawdecisiontree/api-design/tree.dag - Canonical HTML:
/trees/drawdecisiontree/api-design
Questions in this decision tree
- Who are the primary consumers of this API?
- Is low-latency real-time streaming required?
- Does the client need fine-grained control over exactly which fields are fetched?
- Is bidirectional communication (client push AND server push) needed?
- Is strict contract-first API design with generated SDKs a priority?
Possible outcomes
- REST (pragmatic)
- REST + OpenAPI
- GraphQL
- gRPC / Protocol Buffers
- WebSocket / Server-Sent Events
How to use this decision tree
Click "Open interactive version" to step through the questions. Your answers narrow the tree until a recommended outcome is reached. You can also embed this tree on your own site.
More decision trees by Andrew
CI/CD Pipeline Tool Selection
Choosing a CI/CD platform is a long-term infrastructure commitment — pipelines accumulate config, custom scripts, and team muscle memory that make switching painful. This tree eliminates tools that don't fit your source control host, infrastructure model, or team scale, leaving only the options genuinely viable for your situation.
Which cloud provider should I use — AWS, Azure, or Google Cloud?
Answer a few questions to identify the most suitable cloud platform for your workload.
Container Orchestration Platform Selection
Container orchestration is foundational infrastructure — the platform you choose shapes how you deploy, scale, network, and operate every service you run. This tree eliminates options that don't match your operational maturity, cloud provider commitment, and workload complexity, so you land on the platform that fits your team today without over-engineering for a scale you haven't reached.
How do I assess the health of a customer account?
Classify a customer's health score to guide proactive engagement and retention strategy. Use this tree during your regular account reviews or whenever a trigger event—such as a low NPS, a support spike, or a missed check-in—prompts a reassessment. The outcome drives the cadence and urgency of your next CSM action.
How should I escalate this customer issue?
Determine the appropriate escalation path when a customer issue exceeds normal CSM handling. This tree helps you move quickly and confidently when a situation is deteriorating, ensuring the right people are engaged at the right time. Use it the moment you sense an issue may outgrow your ability to resolve it alone.
Is this customer ready for an expansion or upsell conversation?
Evaluate whether an existing customer is ready for an upsell or cross-sell conversation and determine the right next action. Acting on expansion signals too early—before a customer has fully adopted the core product—can damage trust and accelerate churn. This tree helps you distinguish genuine expansion readiness from surface-level interest so you invest your time in opportunities with the highest probability of closing.