Upgrade to Pro — share decks privately, control downloads, hide ads and more …

apidays Paris 2024 - GraphQL Why bother We have...

apidays
December 31, 2024

apidays Paris 2024 - GraphQL Why bother We have REST, Peter Milne, Criteo

GraphQL? Why Bother, We Have REST
Peter Milne, Engineering Program Manager at Criteo

apidays Paris 2024 - The Future API Stack for Mass Innovation
December 3 - 5, 2024

------

Check out our conferences at https://www.apidays.global/

Do you want to sponsor or talk at one of our conferences?
https://apidays.typeform.com/to/ILJeAaV8

Learn more on APIscene, the global media made by the community for the community:
https://www.apiscene.io

Explore the API ecosystem with the API Landscape:
https://apilandscape.apiscene.io/

apidays

December 31, 2024
Tweet

More Decks by apidays

Other Decks in Programming

Transcript

  1. Apidays 2024 GraphQL? “why bother, we have REST” Peter Milne

    – the old man at Criteo le vieux Criteo
  2. 2 In the 1980’s – Data storage Hand crafted –

    you were on your own When I was a 20-something DENTIFICATION DIVISION. PROGRAM-ID. Conditions. AUTHOR. Michael Coughlan. * An example program demonstrating the use of * condition names (level 88's). * The EVALUATE and PERFORM verbs are also used. DATA DIVISION. WORKING-STORAGE SECTION. 01 Char PIC X. 88 Vowel VALUE "a", "e", "i", "o", "u". 88 Consonant VALUE "b", "c", "d", "f", "g", "h" "j" THRU "n", "p" THRU "t", "v" THRU "z". 88 Digit VALUE "0" THRU "9". 88 ValidCharacter VALUE "a" THRU "z", "0" THRU "9". PROCEDURE DIVISION. Begin. DISPLAY "Enter lower case character or digit. No data ends.". ACCEPT Char. PERFORM UNTIL NOT ValidCharacter EVALUATE TRUE WHEN Vowel DISPLAY "The letter " Char " is a vowel." WHEN Consonant DISPLAY "The letter " Char " is a consonant." WHEN Digit DISPLAY Char " is a digit." WHEN OTHER DISPLAY "problems found" END-EVALUATE END-PERFORM STOP RUN.
  3. 3 Before SQL – proprietary data storage DENTIFICATION DIVISION. PROGRAM-ID.

    Conditions. AUTHOR. Michael Coughlan. * An example program demonstrating the use of * condition names (level 88's). * The EVALUATE and PERFORM verbs are also used. DATA DIVISION. WORKING-STORAGE SECTION. 01 Char PIC X. 88 Vowel VALUE "a", "e", "i", "o", "u". 88 Consonant VALUE "b", "c", "d", "f", "g", "h" "j" THRU "n", "p" THRU "t", "v" THRU "z". 88 Digit VALUE "0" THRU "9". 88 ValidCharacter VALUE "a" THRU "z", "0" THRU "9". PROCEDURE DIVISION. Begin. DISPLAY "Enter lower case character or digit. No data ends.". ACCEPT Char. PERFORM UNTIL NOT ValidCharacter EVALUATE TRUE WHEN Vowel DISPLAY "The letter " Char " is a vowel." WHEN Consonant DISPLAY "The letter " Char " is a consonant." WHEN Digit DISPLAY Char " is a digit." WHEN OTHER DISPLAY "problems found" END-EVALUATE END-PERFORM STOP RUN. Before SQL • Index files (IMS, DMS) • One file per “table” • Schema in “working storage” You managed: Schema File location Index and data blocks Compaction Backup Transactions Joins
  4. 4 Before SQL – proprietary data storage DENTIFICATION DIVISION. PROGRAM-ID.

    Conditions. AUTHOR. Michael Coughlan. * An example program demonstrating the use of * condition names (level 88's). * The EVALUATE and PERFORM verbs are also used. DATA DIVISION. WORKING-STORAGE SECTION. 01 Char PIC X. 88 Vowel VALUE "a", "e", "i", "o", "u". 88 Consonant VALUE "b", "c", "d", "f", "g", "h" "j" THRU "n", "p" THRU "t", "v" THRU "z". 88 Digit VALUE "0" THRU "9". 88 ValidCharacter VALUE "a" THRU "z", "0" THRU "9". PROCEDURE DIVISION. Begin. DISPLAY "Enter lower case character or digit. No data ends.". ACCEPT Char. PERFORM UNTIL NOT ValidCharacter EVALUATE TRUE WHEN Vowel DISPLAY "The letter " Char " is a vowel." WHEN Consonant DISPLAY "The letter " Char " is a consonant." WHEN Digit DISPLAY Char " is a digit." WHEN OTHER DISPLAY "problems found" END-EVALUATE END-PERFORM STOP RUN. Before SQL • Index files (IMS, DMS) • One file per “table” • Schema in “working storage” You managed: Schema File location Index and data blocks Compaction Backup Transactions Joins
  5. 5 SQL and Relational Databases: Schema: Data Definition Language (DDL)

    Queries: Data Manipulation Language (DML) Abstractions, compaction, indexing, joins selective columns, aliasing, casting, etc.. … and loads features and tools
  6. 6 Schema: Data Definition Language (DDL) Queries: Data Manipulation Language

    (DML) Abstractions, compaction, indexing, joins selective columns, aliasing, casting, etc.. … and loads features and tools SQL and Relational Databases:
  7. 7 Who am I? – Uncle Pete Australian living in

    Paris - et mon français est horrible Worked on the first commercial email system in 1980’s 44 years as a hardware and software engineer 24 years as a software architect 15 Years as a commercial helicopter pilot CPL(h) Visited 49 countries, worked in 26, lived in 5 Unhealthy interest in Lego, robotics, deep learning. A mega geek and part-time mad scientist
  8. 8

  9. 10 History - Networking in the 80’s IBM SNA –

    Systems network architecture LU6 – Application to application Digital Equipment Corp DecNet Digit Equipment Corp. Networking Channel – Application to application Wang Laboratories WSN – Wang System Networking Remote Port – Application to application Unix – Everyone had a one TCP/IP Sockets – Application to application
  10. 11 History - Networking in the 80’s What you got:

    Application to application communication (L6/L7)
  11. 12 History – Remote Procedure call (late 80’s) Wikipedia. https://en.wikipedia.org/wiki/Remote_procedure_call

    In distributed computing, a remote procedure call (RPC) is when a computer program causes a procedure (subroutine) to execute in a different address space (commonly on another computer on a shared network), which is coded as if it were a normal (local) procedure call, without the programmer explicitly coding the details for the remote interaction. That is, the programmer writes essentially the same code whether the subroutine is local to the executing program, or remote.[1] This is a form of client–server interaction (caller is client, executor is server), typically implemented via a request–response message-passing system
  12. 13 History – Remote Procedure call (late 80’s) What you

    got: Procedure/Function call paradigm with Serialization/De- serialization
  13. 14 History – DCE (Early 90’s) The Distributed Computing Environment

    (DCE) software system was developed in the early 1990s from the work of the Open Software Foundation (OSF), a consortium (founded in 1988) that included Apollo Computer (part of Hewlett- Packard from 1989), IBM, Digital Equipment Corporation, and others. The DCE supplies a framework and a toolkit for developing client/server applications. The framework includes: a remote procedure call (RPC) mechanism known as DCE/RPC a naming (directory) service a time service an authentication service a distributed file system (DFS) known as DCE/DFS DCE represented a big step in the direction of standardisation of architectures, which had previously been manufacturer-dependent. Wikipedia https://en.wikipedia.org/wiki/Distributed_Computing_Environment
  14. 17 History – CORBA (90’s) The Common Object Request Broker

    Architecture (CORBA) is a standard defined by the Object Management Group (OMG) designed to facilitate the communication of systems that are deployed on diverse platforms. CORBA enables collaboration between systems on different operating systems, programming languages, and computing hardware. CORBA uses an object- oriented model although the systems that use the CORBA do not have to be object-oriented. Object Management Group not “Oh My God”
  15. 25 History – RMI (Late 90’s) Java Remote Method Invocation

    (Java RMI) is a Java API that performs remote method invocation, the object-oriented equivalent of remote procedure calls (RPC), with support for direct The original implementation depends on Java Virtual Machine (JVM) class- representation mechanisms and it thus only supports making calls from one JVM to another. The protocol underlying this Java-only implementation is known as Java Remote Method Protocol (JRMP).
  16. 31 History – SOAP (Early 00’s) SOAP (originally Simple Object

    Access Protocol) is a protocol specification for exchanging structured information in the implementation of web services in computer networks. Its purpose is to induce extensibility, neutrality and independence. It uses XML Information Set for its message format, and relies on application layer protocols, most often Hypertext Transfer Protocol (HTTP) or Simple Mail Transfer Protocol (SMTP), for message negotiation and transmission.
  17. 34 History – SOAP (Early 00’s) What you got: RPCs

    and Services thru Firewall Also: … Migraines … Nausea … Hemorrhoids … Self-reflection on career choice
  18. 36 History - { REST } Representational state transfer (REST)

    or RESTful web services is a way of providing interoperability between computer systems on the Internet. REST-compliant Web services allow requesting systems to access and manipulate textual representations of Web resources using a uniform and predefined set of stateless operations. Wikipedia https://en.wikipedia.org/wiki/Representational_state_transfer
  19. 39 Easy Open Powerful CRUD History - { REST }

    What you got: Sensible SOAP ☺
  20. 40 History - { REST } Quick and dirty REST

    is easy • No consistency • Too many ops • Poor separation of concerns
  21. 41 History - { REST } Quick and dirty REST

    is easy • No consistency • Too many ops • Poor separation of concerns Good REST is HARD • Consistency • Contracts: OpenAPI • Events: WebHooks • Multiple Ops: Bulk
  22. 42 History - { REST } Quick and dirty REST

    is easy • No consistency • Too many ops • Poor separation of concerns Good REST is HARD • Consistency • Contracts: OpenAPI • Events: WebHooks • Multiple Ops: Bulk If you do good rest… you have invented a PROPRIETARY “GraphQL-like solution”
  23. 43 History - { REST } If you do good

    rest… you have invented a PROPRIETARY “GraphQL-like solution”
  24. 45 GraphQL - Foundation GraphQL was created in 2012 and

    open sourced by Facebook in 2015. In 2019, Facebook and others created the GraphQL Foundation as a neutral, non-profit home for the GraphQL assets and ongoing collaboration, and hosted by The Linux Foundation. The GraphQL Foundation is a fully neutral home for the GraphQL trademark, and provides a means of collecting and distributing membership dues to support core community infrastructure and programs.
  25. 51

  26. 53 Schema Types Type – read model Input – write

    model Enum – like every other enum Scalar – Int, Float, String, ID, etc. Union Interface – polymorphic specification Describe the data # Marketing Solutions Campaign type MarketingCampaign implements Campaign @key(fields: "id ") { id: ID! # The Campaign name, set by the advertiser. Read-only name: String! # Read-only. The advertiser associated with the Campaign. advertiserId: ID advertiser: Advertiser """ The marketing objective of the Campaign. Can be AppInstall, BrandAwareness, CatalogSales, Conversion, ResellerProgram, StoreSales, Traffic, VideoViews, or Unknown. """ objective: MarketingCampaignObjective # The campaign spend spendLimit: MarketingCampaignSpendLimit # AdSets for the campaign adSets: [AdSet] }
  27. 54 Schema Types Type – read model Input – write

    model Enum – like every other enum Scalar – Int, Float, String, ID, etc. Union Interface – polymorphic specification Describe the data # Marketing Solutions Campaign type MarketingCampaign implements Campaign @key(fields: "id ") { id: ID! # The Campaign name, set by the advertiser. Read-only name: String! # Read-only. The advertiser associated with the Campaign. advertiserId: ID advertiser: Advertiser """ The marketing objective of the Campaign. Can be AppInstall, BrandAwareness, CatalogSales, Conversion, ResellerProgram, StoreSales, Traffic, VideoViews, or Unknown. """ objective: MarketingCampaignObjective # The campaign spend spendLimit: MarketingCampaignSpendLimit # AdSets for the campaign adSets: [AdSet] }
  28. 55 Schema Types Type – read model Input – write

    model Enum – like every other enum Scalar – Int, Float, String, ID, etc. Union Interface – polymorphic specification Describe the data # Marketing Solutions Campaign type MarketingCampaign implements Campaign @key(fields: "id ") { id: ID! # The Campaign name, set by the advertiser. Read-only name: String! # Read-only. The advertiser associated with the Campaign. advertiserId: ID advertiser: Advertiser """ The marketing objective of the Campaign. Can be AppInstall, BrandAwareness, CatalogSales, Conversion, ResellerProgram, StoreSales, Traffic, VideoViews, or Unknown. """ objective: MarketingCampaignObjective # The campaign spend spendLimit: MarketingCampaignSpendLimit # AdSets for the campaign adSets: [AdSet] }
  29. 56 Schema Relationships Field type • Optional • Exactly one

    • Many # Marketing Solutions Campaign type MarketingCampaign implements Campaign @key(fields: "id ") { id: ID! # The Campaign name, set by the advertiser. Read-only name: String! # Read-only. The advertiser associated with the Campaign. advertiserId: ID advertiser: Advertiser """ The marketing objective of the Campaign. Can be AppInstall, BrandAwareness, CatalogSales, Conversion, ResellerProgram, StoreSales, Traffic, VideoViews, or Unknown. """ objective: MarketingCampaignObjective # The campaign spend spendLimit: MarketingCampaignSpendLimit # AdSets for the campaign adSets: [AdSet] } Describe the relationships
  30. 57 Schema Relationships Field type • Optional • Exactly one

    • Many # Marketing Solutions Campaign type MarketingCampaign implements Campaign @key(fields: "id ") { id: ID! # The Campaign name, set by the advertiser. Read-only name: String! # Read-only. The advertiser associated with the Campaign. advertiserId: ID advertiser: Advertiser """ The marketing objective of the Campaign. Can be AppInstall, BrandAwareness, CatalogSales, Conversion, ResellerProgram, StoreSales, Traffic, VideoViews, or Unknown. """ objective: MarketingCampaignObjective # The campaign spend spendLimit: MarketingCampaignSpendLimit # AdSets for the campaign adSets: [AdSet] } Describe the relationships
  31. 58 Schema Relationships Field type • Optional • Exactly one

    • Many # Marketing Solutions Campaign type MarketingCampaign implements Campaign @key(fields: "id ") { id: ID! # The Campaign name, set by the advertiser. Read-only name: String! # Read-only. The advertiser associated with the Campaign. advertiserId: ID advertiser: Advertiser """ The marketing objective of the Campaign. Can be AppInstall, BrandAwareness, CatalogSales, Conversion, ResellerProgram, StoreSales, Traffic, VideoViews, or Unknown. """ objective: MarketingCampaignObjective # The campaign spend spendLimit: MarketingCampaignSpendLimit # AdSets for the campaign adSets: [AdSet] } Describe the relationships
  32. 59 Schema Relationships Field type • Optional • Exactly one

    • Many # Marketing Solutions Campaign type MarketingCampaign implements Campaign @key(fields: "id ") { id: ID! # The Campaign name, set by the advertiser. Read-only name: String! # Read-only. The advertiser associated with the Campaign. advertiserId: ID advertiser: Advertiser """ The marketing objective of the Campaign. Can be AppInstall, BrandAwareness, CatalogSales, Conversion, ResellerProgram, StoreSales, Traffic, VideoViews, or Unknown. """ objective: MarketingCampaignObjective # The campaign spend spendLimit: MarketingCampaignSpendLimit # AdSets for the campaign adSets: [AdSet] } Describe the relationships
  33. 61 CQRS Pattern Write Read Query Model (physical read model)

    Command Model (physical write model) Client Entity store (database) Event Store Event Canonical Model
  34. 62 Schema Operations Query One or more object graph reads

    Mutation One or more Writes or Commands Subscription Subscribe to events emitted by the server type Query { marketingCampaign(id: ID!): MarketingCampaign marketingCampaigns( advertiserIds: [ID!] offset: Int = 0 limit: Int = 100 ): [MarketingCampaign] retailMediaCampaign(id: ID!): RetailMediaCampaign retailMediaCampaigns( accountId: ID! offset: Int = 0 limit: Int = 100 ): [RetailMediaCampaign] campaigns( accountId: ID! advertiserIds: [ID!] offset: Int = 0 limit: Int = 100 ): [Campaign] } type Mutation { newMarketingCampaign( adveriserId: ID! campaign: NewMarketingCampaign! ): MarketingCampaign! updateMarketingCampaigns(campaign: [UpdateMarketingCampaign!]!): [ID] updateMarketingCampaign( id: ID! campaign: UpdateMarketingCampaign! ): MarketingCampaign
  35. 63 type Query { marketingCampaign(id: ID!): MarketingCampaign marketingCampaigns( advertiserIds: [ID!]

    offset: Int = 0 limit: Int = 100 ): [MarketingCampaign] retailMediaCampaign(id: ID!): RetailMediaCampaign retailMediaCampaigns( accountId: ID! offset: Int = 0 limit: Int = 100 ): [RetailMediaCampaign] campaigns( accountId: ID! advertiserIds: [ID!] offset: Int = 0 limit: Int = 100 ): [Campaign] } type Mutation { newMarketingCampaign( adveriserId: ID! campaign: NewMarketingCampaign! ): MarketingCampaign! updateMarketingCampaigns(campaign: [UpdateMarketingCampaign!]!): [ID] updateMarketingCampaign( id: ID! campaign: UpdateMarketingCampaign! ): MarketingCampaign Schema Operations Query One or more object graph reads Mutation One or more Writes or Commands Subscription Subscribe to events emitted by the server
  36. 64 ): [RetailMediaCampaign] campaigns( accountId: ID! advertiserIds: [ID!] offset: Int

    = 0 limit: Int = 100 ): [Campaign] } type Mutation { newMarketingCampaign( adveriserId: ID! campaign: NewMarketingCampaign! ): MarketingCampaign! updateMarketingCampaigns(campaign: [UpdateMarketingCampaign!]!): [ID] updateMarketingCampaign( id: ID! campaign: UpdateMarketingCampaign! ): MarketingCampaign newRetailMediaCampaign( accountId: ID! campaign: NewRetailMediaCampaign! ): RetailMediaCampaign! updateRetailMediaCampaign( id: ID! campaign: UpdateRetailMediaCampaign! ): RetailMediaCampaign! } type Subscription { marketingCampaignCreated(advertiserId: ID!): MarketingCampaign! retailMediaCampaignCreated(accountId: ID!): RetailMediaCampaign! } Schema Operations Query One or more object graph reads Mutation One or more Writes or Commands Subscription Subscribe to events emitted by the server
  37. 66 ): [RetailMediaCampaign] campaigns( accountId: ID! advertiserIds: [ID!] offset: Int

    = 0 limit: Int = 100 ): [Campaign] } type Mutation { newMarketingCampaign( adveriserId: ID! campaign: NewMarketingCampaign! ): MarketingCampaign! updateMarketingCampaigns(campaign: [UpdateMarketingCampaign!]!): [ID] updateMarketingCampaign( id: ID! campaign: UpdateMarketingCampaign! ): MarketingCampaign newRetailMediaCampaign( accountId: ID! campaign: NewRetailMediaCampaign! ): RetailMediaCampaign! updateRetailMediaCampaign( id: ID! campaign: UpdateRetailMediaCampaign! ): RetailMediaCampaign! } type Subscription { marketingCampaignCreated(advertiserId: ID!): MarketingCampaign! retailMediaCampaignCreated(accountId: ID!): RetailMediaCampaign! } Schema Operations Query One or more object graph reads Mutation One or more Writes or Commands Subscription Subscribe to events emitted by the server
  38. 67 Why use GraphQL More than one client (e.g. web

    + iOS) Care about latency and bandwidth A microservices architecture REST API has gotten so complicated that it’s a significant drag on product development. Decouple frontend and backend to prevent leakage One endpoint to access your data Retrieve only the data your client needs in a single request (flexibility) No need to tailor endpoints for your views No versioning issues Deprecation at a field level Schema discovery
  39. 68 Why use GraphQL More than one client (e.g. web

    + iOS) Care about latency and bandwidth A microservices architecture REST API has gotten so complicated that it’s a significant drag on product development. Decouple frontend and backend to prevent leakage One endpoint to access your data Retrieve only the data your client needs in a single request (flexibility) No need to tailor endpoints for your views No versioning issues Deprecation at a field level Schema discovery Frontend Backend Schema
  40. 70 The whole elephant Whole object when you only need

    a portion You request an Elephant but only need it’s tusk and 1 toe
  41. 71 The whole elephant 6 REST calls (without projection) -

    Elephant - Head - Tusks - Body - Legs - Toes
  42. 73 Ask for what you want and Only what you

    want In the Shape that you want Just like SQL
  43. 74 Real Example Lineitem detail with campaign name Scenario: A

    web component displays a Lineitem’s details, with Budget information for Edit (form); with a the owning Campaign Name and ID in a header. 7 One operation in GraphQL Three operations in REST
  44. 77 Endpoint inconsistency REST Multiple endpoints operate with the same-ish

    object with inconsistencies GraphQL Single endpoint Interface polymorphism
  45. 80

  46. 81 GraphQL - Why Simplify UI development - One Dialect

    for Client Server communications - One Endpoint Clean separation of concern Re-use, regulate and aggregate
  47. 83 SQL has: Schema: Data Definition Language Queries: Data Manipulation

    Language Compaction, indexing, joins selective columns, aliasing … and loads features and tools
  48. 84 GraphQL has: Schema: Schema Definition Language Operations: Queries, Mutations,

    Subscriptions Relationships, selective columns, aliasing … and Apollo Client and Server have loads features and tools
  49. 87 Strategy without tactics is the slowest route to victory.

    La stratégie sans tactique est le chemin le plus lent vers la victoire. Tactics without strategy is the noise before defeat. La tactique sans stratégie est le bruit avant la défaite. - Sun Tzu
  50. 89 shanty town – bidonville city planning - aménagement de

    la ville Code First Schema First Strategic
  51. 90 Sweet spot shanty town – bidonville city planning -

    aménagement de la ville Code first Schema first Tactical vs Strategic
  52. 92 GraphQL is not a silver bullet Schema (contract) first

    design type Query { marketingCampaign(id: ID!): MarketingCampaign marketingCampaigns( advertiserIds: [ID!] offset: Int = 0 limit: Int = 100 ): [MarketingCampaign] retailMediaCampaign(id: ID!): RetailMediaCampaign retailMediaCampaigns( accountId: ID! offset: Int = 0 limit: Int = 100 ): [RetailMediaCampaign] campaigns( accountId: ID! advertiserIds: [ID!] offset: Int = 0 limit: Int = 100 Canonical Model – source of truth
  53. 93 GraphQL is not a silver bullet If you suck

    at • REST you will suck at GraphQL • SOA you will suck at GraphQL If you service design is poor … GraphQL is not magic
  54. 94 Technologies I have tried Scala https://github.com/sangria-graphql/sangria C# Platform |

    ChilliCream GraphQL Platform Java https://github.com/graphql-java/graphql-java Node.js https://github.com/apollographql/apollo-server Apollo Client and Server development is approx. 10x faster/easier compared to Scala Mature tools Declarative Schema Easy to learn
  55. 95 Technologies I have tried Scala https://github.com/sangria-graphql/sangria C# Platform |

    ChilliCream GraphQL Platform Java https://github.com/graphql-java/graphql-java Node.js https://github.com/apollographql/apollo-server Apollo Client and Server development is approx. 10x faster/easier compared to Scala Mature tools Declarative Schema Easy to learn Avertissement: histoire ennuyeuse de vieil homme en cours
  56. 96 Advertencia: historia aburrida del viejo en progreso Technologies I

    have tried Scala https://github.com/sangria-graphql/sangria C# Platform | ChilliCream GraphQL Platform Java https://github.com/graphql-java/graphql-java Node.js https://github.com/apollographql/apollo-server Apollo Client and Server development is approx. 10x faster/easier compared to Scala Mature tools Declarative Schema Easy to learn