Intro
AWS AppSync is a fully managed serverless service from AWS for building scalable and resilient GraphQL APIs.
The AWS Well-Architected Framework and Serverless Application Lens offer best practices for building serverless applications in the cloud. This post will show how to apply these practices when creating GraphQL APIs with AWS AppSync, aligned with the Well-Architected pillars.
Operational Excellence
Focuses on running and monitoring systems to deliver business value, and continuously improving processes and procedures.
Enable Observability
Observability is the ability to understand the internal state of a system based on the data it generates, which includes logs, metrics, and traces. Together, these components enable you to monitor, troubleshoot, and optimise system behaviour efficiently.
AWS AppSync has built-in integration with AWS Cloudwatch for logs and metrics and X-Ray for tracing.
AppSync supports two types of logging: Request-level logging and Field-level logging. Field-level logging supports five logging levels (None
, Error
, Info
, Debug
and All
), providing flexibility in the amount of detail captured for each GraphQL query.
AppSync captures a variety of default and enhanced metrics with detailed data points to monitor API performance and usage.
AppSync uses X-Ray to capture traces, allowing us to track the lifecycle of API requests, measure execution times for detailed performance analysis, and identify errors for easier troubleshooting.
When using Lambda resolvers, implement logging and manually instrument traces using AWS X-Ray SDK. Utilise libraries like Powertools for lambda and Middy
Use Infrastructure as Code (IaC)
For prototyping and deploying, consider using Infrastructure as Code (IaC) to enable tracking of changes using version control and releases. Cloudformation, Terraform, AWS SAM, and AWS CDK are a few examples.
If you are using AWS CDK, this CDK construct simplifies writing AppSync resolvers using Typescript.
Test, Test, Test
Testing is essential for building and releasing a bug-free system. From Day 0, create and implement a testing strategy for APIs built using AppSync.
Security
Ensures data protection, confidentiality, and integrity through identity management, security monitoring, and incident response.
Set up Authorisation
Unprotected APIs are easy targets for attackers seeking valuable data. AppSync offers built-in authorization support with API keys, IAM, OIDC, Cognito user pools, and Lambda authorizers.
Use Lambda authoriser for any custom/proprietary authorisation logic.
AppSync also has Cognito group-based authorisation that can be easily defined in GraphQL schema.
When using API keys, consider rotating them for better security and set up monitoring API key usage to identify any unusual activity, as they are less secure when compared to other types.
Use Private API
For applications running in AWS VPC or on-premises that need access to AppSync APIs, Create private APIs to reduce the attack surface.
Set up Web Application Firewall (WAF)
AWS WAF (Web Application Firewall) is a managed service that helps protect web applications from common threats and vulnerabilities
Configuring AWS Web Application Firewall (WAF) for AWS AppSync helps to enhance the security of your GraphQL APIs by providing multiple layers of protection.
Create roles with the least permissions
Roles created for resolvers should be set up with the most limited permissions to adhere to the principle of least privilege.
Keep secrets away from resolver code
You should not hard code API keys or secrets in resolver code; Instead, store it in Secrets Manager or Parameter Store and retrieve it.
With a pipeline resolver, the operation to fetch secrets can be executed before processing the external request. One downside would be it will impact the performance as the resolver needs to fetch a secret for each API request.
Disable Introspection
AppSync supports GraphQL introspection, a feature that allows clients to query the schema of a GraphQL API. It enables users to discover the types, fields, queries, mutations, and subscriptions available in the API, as well as the relationships between them.
Disable introspection for public users when applicable to enhance security and protect against vulnerabilities and data breaches.
Configure query depth limits
In AWS AppSync, query depth limit refers to a safeguard mechanism that restricts the maximum depth of nested queries allowed in a single GraphQL request. This limit helps prevent excessively deep or complex queries that could lead to performance issues or denial-of-service (DoS) attacks on your API.
Enforce reasonable limits on how deep queries can go, ensuring better overall stability and security of the application.
Reliability
Involves designing systems that recover from failures and dynamically meet demand.
Leverage Caching
AppSync supports both full request and per-resolver caching. Enable caching to reduce the load on backend systems.
Build reliable Lambdas
When using a Lambda resolver, implement retry logic to handle transient errors, allowing recovery and improving the function's reliability.
Allocate appropriate memory and set reasonable timeout limits based on the lambda's needs to prevent unnecessary failures.
As we all know, Everything fails all the time, implement error handling in Lambdas
Enable Pagination
AppSync uses token-based pagination; a token is used to specify the record after which additional items should be fetched, along with the page size.
Implement pagination to reduce the load on backend systems, improving API stability and reliability.
Performance Efficiency
Emphasises using computing resources efficiently to meet system requirements and maintain responsiveness.
Leverage Caching
Caching boosts the performance and reduces the latency of APIs built with AppSync.
Avoid Lambda resolver
AWS AppSync connects directly with data sources outside of Lambda. Using these connections directly reduces latency by eliminating one network hop, which enhances performance.
Optimise Lambda
When using Lambda resolvers, seek optimisations to enhance performance if Lambda is affecting overall latency.
Some optimisation techniques include reducing cold starts, keeping Lambda functions warm, enabling keep-alive for HTTP calls, configuring the required memory, using alternate runtimes like LLRT & Rust and using connection pooling.
Consider trade-offs when optimising Lambdas, as premature optimisations may not be necessary and could offer a low Return on Investment (ROI).
Utilise Subscriptions Effectively
AWS AppSync subscriptions are a feature that allows clients to receive real-time updates from a GraphQL API.
With AppSync subscriptions, ensure that the payload size is minimal and implement filtering on subscriptions to send only relevant data to clients.
Cost Optimisation
Helps control costs by using the right resources, eliminating waste, and scaling effectively.
Leverage Caching
Caching reduces the need to invoke resolvers for repeated requests, which in turn lowers the cost of Lambda invocations, DynamoDB queries, and other operations.
Setting up caching incurs initial costs since it relies on instances rather than being serverless. However, as AppSync serves more requests using the cache, it reduces overall costs.
Avoid Lambda resolver
As stated in the performance pillar above, Directly interacting with data sources reduces the cost of using Lambda.
Log what you need
Enabling verbose and full logging in AppSync can quickly increase your CloudWatch costs. Choose what to log carefully for troubleshooting.
Set a retention period for CloudWatch log groups, as application logs are usually needed for 2-4 weeks for troubleshooting. For longer storage, use AWS S3 with lifecycle policies to reduce costs.
AppSync does not support log sampling by default. Implement a custom sampling strategy to log detailed data every X minutes over Y hour(s).
Sustainability
Minimises environmental impact through efficient resource management and sustainable practices.
There are no sustainability practices to implement as the serverless paradigm continuously increases efficiency and reduces energy consumption as stated in the Serverless Architecture Lens
Outro
Building well-architected AWS AppSync GraphQL APIs requires a comprehensive approach that considers all aspects of the Serverless Architecture Lens. By following best practices and utilizing AWS AppSync's integration capabilities, you can create scalable, secure, and efficient GraphQL APIs for modern applications.
Remember, building a well-architected solution is an ongoing process. Regularly review your architecture against these pillars and make improvements as your application evolves.
Top comments (1)
Thanks so much for providing practical advice and valuable insights. Extensive coverage and depth. The way you related everything back to the AWS Well-Architected Framework and Serverless Architecture Lens is of immense value. Thanks again for your invaluable input.