GraphQL is mature enough, and has been around us for long enough, that many articles sharing best practices have been published by the community. These guides involve pretty much all aspects of GraphQL, including schema design, naming conventions, security handling and providing meaningful errors, among others.
These are some of the most compelling guides out there on best practices in GraphQL.
Article GraphQL Resolvers: Best Practices describes how to best create field resolvers. Even though it is aimed at Node.js servers (PayPal's infrastructure is based on Express), several of his lessons can also be applied for other technologies, including PHP.
The main takeaways are:
Fetching and passing data from parent-to-child should be used sparingly.
Use libraries like dataloader to de-dupe downstream requests.
Be aware of any pressure you’re causing on your data sources.
Don’t mutate “context”. Ensures consistent, less buggy code.
Write resolvers that are readable, maintainable, testable. Not too clever.
Make your resolvers as thin as possible. Extract out data fetching logic to re-usable async functions.
OWASP (Open Web Application Security Project) is a nonprofit foundation that works to improve the security of software. It does research on how different technologies are vulnerable to exploits, and thoroughly describes solutions to the security issues, making it easier for developers to prevent attacks.
OWASP has published the GraphQL Cheat Sheet, explaining which are the most common attacks and biggest security issues in GraphQL, and how to address them.
Common attacks to GraphQL are:
Injection - this usually includes but is not limited to:
SQL and NoSQL injection
OS Command injection
SSRF and CRLF injection/Request Smuggling
DoS (Denial of Service)
Abuse of broken authorization: either improper or excessive access, including IDOR
Batching Attacks, a GraphQL-specific method of brute force attack
Abuse of insecure default configurations
OWASP then provides recommendations on how to avoid each of these.
Also from the Apollo team is site Principled GraphQL which explains that GraphQL is not only a specification but, possibly more importantly, an interface to interact with the data "graph" from our company.
Through a list of 10 principles, this site describes how to make the most out of the single graph:
One Graph: Your company should have one unified graph, instead of multiple graphs created by each team.
Federated Implementation: Though there is only one graph, the implementation of that graph should be federated across multiple teams.
Track the Schema in a Registry: There should be a single source of truth for registering and tracking the graph.
Abstract, Demand-Oriented Schema: The schema should act as an abstraction layer that provides flexibility to consumers while hiding service implementation details.
Use an Agile Approach to Schema Development: The schema should be built incrementally based on actual requirements and evolve smoothly over time.
Iteratively Improve Performance: Performance management should be a continuous, data-driven process, adapting smoothly to changing query loads and service implementations.
Use Graph Metadata to Empower Developers: Developers should be equipped with rich awareness of the graph throughout the entire development process.
Access and Demand Control: Grant access to the graph on a per-client basis, and manage what and how clients can access it.
Structured Logging: Capture structured logs of all graph operations and leverage them as the primary tool for understanding graph usage.
Separate the GraphQL Layer from the Service Layer: Adopt a layered architecture with graph functionality broken into a separate tier rather than baked into every service.