Use graphQL with API Gateway (apollo-server-lambda) vs. AppSync - amazon-web-services

This is a question keeps confusing me. Although AppSync is marketed as for GraphQL while API Gateway is for REST. But API Gateway could also work with GraphQL via apollo server in lambda.
So what actually makes one a better option over the other?

It depends on how much control you want over your backend service execution, how much code you feel like writing, and then of course how much you want to pay.
With API Gateway and Lambda you are writing a handler function that executes a full graphql request against your resolver definitions that you write in whatever language your Lambda runtime is set to. You have to consider how much memory your application will need, and what kind of features you want to support. You will also need to do some legwork to get subscriptions working with websockets.
AWS AppSync is more of a managed service, where you register your GraphQL schema with AppSync and the service takes care of things like query validation, batching calls, and of course out-of-the-box subscriptions. In it you only need to define how you want to "map" the GraphQL request using VTL (Velocity Templating Language) to define calls to your downstream data sources ie. specifically DynamoDB, ElasicSearch, HTTP, Aurora Serverless RDS, or Lambda. Keep in mind, the Lambda functions you write for AppSync only have to handle a single resolver, whereas with Apollo Server you are writing all of the resolver logic in your code.
Ultimately whichever way you choose has its pros and cons. With Apollo Server on Lambda you get to control the full HTTP GraphQL request cycle at the expense of additional complexity to do so. With AppSync you have a more "managed" service where you only need to define the resolvers to talk to your data sources (and in many cases, these can be auto-generated for you using Amplify CLI) at the expense of having finer control over the whole GraphQL request.

Related

Logging effeciently for AWS Lambda

I'm using serverless framework to enable hosting my functions on AWS Lambdas. For development, I'm using Kotlin.
Since I wanted to re-use resources ( like DB connection ) by a particular lambda, I have grouped apis which have the same handler function. Like all /posts related apis will be handled by PostHandler. Internally, based on routeKey, I'm assigning requests to concerned functions.
This means that for all /posts endpoints ( like GET /posts/{id}, POST /posts etc.) they all get logged to the same CloudWatch log group. This was becoming a problem. Since I was using an API Gateway, I also enable access logging at API Gateway level. This resolved my issue when I'm directly hitting an api.
However, I also have a service which would like to call these lambdas directly ( it could be lambda of that service invoking lambdas of my service or an EC2/ECS instance invoking lambdas of my service ). In this case, we would directly be using lambdas and no ApiGateway is involved. How can I maintain logging for different endpoints in this case?
It's hard to tell what the actual question is, I think you're saying that it's hard to differentiate between the different use cases and requests?
I would recommend using structured logs (logging as JSON) and then using CloudWatch Logs Insights to query for the specific information you need. For example, you could log a request-id with each message and then query on the request-id later. You could also do the same with a shared id between other services which would give you end-to-end log visibility.

How to display data from DynamoDB on an AWS S3 hosted static webpage

I have a system which uses AWS IoT to send data to a DynamoDB table. This is simple weather data and stores time, temperature, humidity and pressure. So far that side is working well.
I want to display data from this table on a webpage hosted on S3. In its most simple form this would just display the latest row of data. I had though that this would be a case of a simple client-side javascript to query the database, but looking on Amazon it gets quite complicated with Lambda functions called through API gateway using IAM to certify.
Is there a simpler way to go about this? Data should be publicly readable, and non-writeable, so I thought should be easier than what I have read so far.
Please have a look at the Simple Web Service CDK Pattern. It helps you create a simple end-to-end service using API Gateway, a Lambda function, and access to a DynamoDB table with just a few lines of code. It is available in multiple programming languages.
As a general note: Whenever you want to provide dynamic content, you need some kind of application that takes care of it. An API Gateway backed by an AWS Lambda function is no more complicated than running a web server with all the undifferentiated heavy lifting like network configuration, firewall setup, OS patching, and maintenance. And proper handling of identity and access control needs to be done in any case.
If you really want to just display the latest row, and you prefer to keep you webpage as static as possible, I would consider just writing out the latest row of dynamodb to a simple json file using whatever backend process you want, then that file can be consumed by your front end application without having to worry about IAM Credentials or even the AWS JS SDK - keep it as simple and lightweight as possible.
No need to repeatedly hit your dynamodb to pull back the same data for each page load either - which should also save you some money in the long run.
There is a in-browser JavaScript SDK. It allows the JavaScript on your web page to make calls directly to DynamoDB, without having to make API calls through API Gateway that trigger a Lambda function that itself makes calls to DynamoDB on your behalf.
The main consideration here is how to authenticate your web browser client. It cannot make DynamoDB API calls without AWS credentials. I'm assuming that you have no server-side component that can return AWS credentials to the client.
You could embed read-only, minimally-permissioned AWS credentials in the page itself - this is definitely not a best practice, but it's simple and in some cases might be acceptable. Other options include requiring the web site user to authenticate via Web Identity Federation, which would dynamically yield a set of usable, time-limited AWS credentials. Another, more sophisticated option, would be AWS Amplify which supports both authenticated and unauthenticated clients. This is generally preferable to hard-coding (read-only) AWS credentials in a web page but is a little more complex to set up.
There is also a blog post: Dynamic Websites Using the AWS SDK for JavaScript in the Browser.
In all these scenarios, the page itself would make API calls directly to DynamoDB, and you should ensure that the IAM role associated with the credentials is heavily restricted (just the relevant DynamoDB table(s) and just the necessary query/get permissions).

Calling lambda from another lambda or exposing api through api-gateway

I am contemplating if I should invoke lambda directly from another lambda or should I expose api through api-gateway in front of lambda. I am looking for pros and cons for both.
Approach #1 Using API Gateway
API Gateway and Lambda have one of the best integrations for serverless applications. It is very widely used and offers a ton of features - proxy integration, mapping templates, custom domain names and different types of authentication.
However, with these pros comes the cons due to some limits with using API Gateway. API Gateway has a default integration time out (a hard limit) of 29 seconds - which means the Lambda function needs to send back a response to API within this time frame or API fails with a 504 response. You may review other limits related to API Gateway here.
Approach #2 Lambda invoking Lambda
I'm not a big fan of this approach and have multiple reasons for it. I'll start with the additional code you have to write - same task with better features can be done by API Gateway with simple configurations on the AWS console.
A container calling another container(Lambda) can result it container-related problems - networking, container reuse and even managing IAM permissions properly.
Also, a Lambda function can be invoked by only three options - SDK, CLI or an entity that has "Invoke" permission. So basically, you need to have some kind of resource in front of your first Lambda to invoke it which will then invoke the second. In my opinion, API Gateway is the best front-end you can have for Lambda which is exactly AWS had in mind building these two services.
One of the pros I can think of this approach is the time out value - Lambda can run for up to max of 15 mins. Unless your client does not require a response back pretty quickly, you can run these two Lambda functions for a longer time to execute code.
Summary
All the above information was pretty general for anyone looking to use API Gateway and Lambda. I'll say it again that using API Gateway is a more convenient and useful approach however it may depend on your use-case. Hope this helps!

Serverless graphql split into micro services

How can i split my serverless graphql endpoint which runs in one lambda function into multiple micro lambda functions for scalability?
is it need to have multiple graphql end points ? or need to have only one graphql endpoint and resolvers split into seperate lambda functions ? what is the best architecture ?
Usually, you access the entire GraphQL API with a single endpoint.
From GraphQL.org:
GraphQL APIs are organized in terms of types and fields, not endpoints. Access the full capabilities of your data from a single endpoint. [emphasis added]
Of course, you could have multiple GraphQL APIs but those would be like separate services and your clients would need which one to access for which data.
You can have a single GraphQL endpoint and then dispatch some work to multiple Lambda functions but it doesn't necessarily need to be more scalable than a single function. Keep in mind that this single function will be run possible multiple times so having one function that does two things is not less scalable than two functions that do one thing each.
For example How to write GraphQL Apps using AWS Lambda
on Cloud Academy recommends using a single AWS Lambda function for the entire API, using Express.
Maybe some other ways to build your service may be better suited to your needs, e.g. see Designing a GraphQL API on AWS AppSync Developer Guide.

Serverless - Options for communicating between services?

I have a few different services (generated by the Serverless Framework) that need to communicate between each other. The data is sensitive and requires authentication.
My current strategy is to create an api key for each service communicate between services using json web token like the token below.
fM61kaav8l3y_aLC/3ZZF7nlQGyYJsZVpLLiux5d84UnAoHOqLPu4dw3W7MiGwPiyN
What are some other options for communicating between services? Are there any downsides to this approach? To reiterate, the request needs to be authenticated and appropriately handle sensitive data.
Do you need sync or async communication?
A good approach would be to use events, because aws-lambda is designed as an event based system. So you could use SNS or SQS to decouple your services.
If you just want to make calls from one service to another you could invoke the lambda function directly via the aws-sdk see docs. So you would not add an API Gateways endpoint and your lambdas would stay private.
To better anwser your question you should give a short overview of your application and and an example of an interservice call you would make.
As I understand it, you intend to make the various functions in a given a service private. In doing so, each service will likely have serverless.yml file that resembles the following:
Image shows the setup for api keys used with a serverless framework rest api
While this is a suitable approach, it is less desirable than using ** Custom Authorizers**.
Custom Authorizers allow you to run an AWS Lambda Function before your targeted AWS Lambda Function. This is useful for Microservice Architectures or when you simply want to do some Authorization before running your business logic.
If you are familiar with the onEnter function when using ReactRouter, the logic among Custom Authorizers is similar.
Regarding implementation, since different services are leveraged to deploy various functions, consider deploying the function to AWS and noteing the ARN of the Lambda function. Follow these links to see the appropriate setup for the custom authorizer.
These images show the serverless.yml file for using custom authorizers when the authorizers are not part of the service but rather deployed on lambda already
The following github project aws-node-auth0-custom-authorizers-api/frontend is a good example of how to implement Custom Authorizers when the authorizer funciton is in the same service as the private function. Note your situation differs slightly yet you should expect their authorizer function logic to be simliar - only the project structure should differ