How to reject the same POST request sent twice in a short gap of time - amazon-web-services

I am wondering if there is a standard way to reject requests with the same body sent within a few seconds at the API gateway itself.
Forex: Reddit rejects if I try to post the same content within few seconds in a different group. Similarly, if I make a credit card payment for the second time, it automatically rejects it.
I am wondering if there is a way to have the same behavior in the AWS API gateway itself so that we are not handling it in lambda functions with dynamoDB and stuff.
Looking forward to efficient ways of doing it.

The API Gateway currently doesn't offer a feature like that, you'd have to implement this yourself.
If I was to implement this, I'd probably use an in-memory cache like ElastiCache for Redis or Memcached as the storage backend for deduplications.
For each incoming request I'd determine what makes it unique and create a hash from that.
Then I check if that hash value is in the cache already. If that's the case it 's a duplicate and I reject the request. If it isn't already in the cache, I'd add it with a time to live of n seconds (The time interval in which I wish to deduplicate).

Related

How to clear an AWS Lambda cache (or force a cold start)

The short version:
If I am caching values in my lambda container, how can I clear this cache? I guess I could redeploy the lambda, which will force all new requests to initiate a new cold start, but this doesn't seem like a nice solution.
The long version:
I am writing a custom authorizer for AWS API Gateway (in Python) that does two things:
It gets an api-key from an http header and looks it up in a dynamo table to verify it is valid (and get some attributes attached to it).
It verifies a JWT token (using some of the attributes from #1).
After following some code (this code), I learnt that I can cache values "globally" that can be re-used across invocations of the lambda, great! But if I cache say, the dynamodb response when looking up the api key, what if I have to revoke / issue a new api key at some point?
I'd like to be able to ensure that my lambda cache gets wiped somehow.
Short answer: You can force a new container for each invoke by calling the UpdateFunctionCode or UpdateFunctionConfiguration before exiting the execution for the same function. You can keep changing function time out before returning the response and the next invoke will spin up a new execution environment (container/sandbox) with a cold start penalty.
The right approach: If you are caching the function variables, you can clear them off inside the handler and continue with the execution logic. This will ensure you are not facing cold start penalties for subsequent invocations and you can in control of choosing the "right" values.
This can be better explained in using database clients. You can create the client outside the handler, but for every invoke verify if the client is valid. Recreate the client inside the handler if the original is now invalid. This will save you some processing time - as the CPU is throttled when the function hits the handler.
Since you are working with API Gateway, the cold start penalties will contribute towards API's Integration timeout (hard limit of 29 seconds for auth and backend combined); and I will try to avoid forcing cold start as much as possible.

Django(2.11) simultaneous (within 10ms) identical HTTP requests

Consider a POST/PUT REST API (using DRF).
If the server receives request1 and within a couple of ms request2 with identical everything to request1 (duplicate request), is there a way to avoid the request2 to be executed using some Django way? Or Should I deal with it manually by some state?
Any inputs would be much appreciated.
There isn't anything out of the box so you would need to write something your self potentially a piece of custom middleware (https://docs.djangoproject.com/en/3.0/topics/http/middleware/) would be best as then it would run over all of the requests. You would need to capture and exam the requests so you'd need a fast storage of some sort such as a memory store.
You could also look into the python asynco library - https://docs.python.org/3/library/asyncio-sync.html
Another possible solution would be using a FIFO message queue which is configured to support de-duplication based on content. This would turn the request into an deferred process though so it may not be suitable for your needs.

Workaround aws apigateway timeout with lambda - asynchronous processing

I have a serverless backend running on lambda. The runtime usually varies betweeen 40-250s which is over the apigateway max allowed runtime (29s). As such I think my only option is to resort to asynchronous processing. I get the idea behind it, but help online seems sparse and I'd like to know if there are any best practices out there? Or what would be the simplest way for me to get around this timeout problem–using asynchronous processing or other?
It really depends on your use case. But probably an asynchronous approach is best fitted for this scenario given that it's not usually a good idea from the calling side of your API to wait 250 seconds to get the reply back (probably that's why the 29s limitation on API Gateway).
Asynchronous simply means that you will be replying back from Lambda saying that you received the request and you are going to work on it but it will be available only later.
Then, you will be changing the logic on the client side, too, to check back after some time or perform some checks in a loop until the requested resource is ready.
Depending on what work needs to be done you could create an S3 bucket on the fly and reply back to the client with an S3 presigned URL. Then your worker will upload their results to the S3 bucket and the client will poll that bucket for the results until they are present.

AWS Lambda - single vs multile productId

I have a use case where the client app will make a REST call with MULTIPLE product identifiers and get their details. I have a lambda function(exposed by API gateway) which can take a SINGLE product id and get it's detail. I need to get them to work together.. What is a good solution for this?
Modify the client app so it makes single product Id requests. No change in Lambda function required then. But this increases client app network calls as it will invoke the lambda for each productId separately..
Modify the lambda function so that it can handle multiple product id's in the same call.. But this increases lambda response time..
I was also thinking about creating a new lambda function which takes in the multiple productId's and then calls the single product lambda function.. But not sure how to aggregate the responses before sending back to client app.
Looking for suggestions..
Option 1 is less optimal as it will move the chatty protocol between the client to server.
If there are no users of a single Id then I would not keep that one alive. (not option #3)
Depending on your language of choice - it might be best to implement 2 (or 3 for this matter). node.js (and C# too btw) makes it very easy to perform multiple calls in parallel (async calls) and then wait for all results and return to the client.
This means that you will not wait X time more - just a bit more, aligned with your slowest call.
ES6 (modern JS, supported by Lambda) now supports Promise.all() for this purpose.
C# also natively supports these patterns with Task.WaitAll()

AWS API Gateway Cache - Multiple service hits with burst of calls

I am working on a mobile app that will broadcast a push message to hundreds of thousands of devices at a time. When each user opens their app from the push message, the app will hit our API for data. The API resource will be identical for each user of this push.
Now let's assume that all 500,000 users open their app at the same time. API Gateway will get 500,000 identical calls.
Because all 500,000 nearly concurrent requests are asking for the same data, I want to cache it. But keep in mind that it takes about 2 seconds to compute the requested value.
What I want to happen
I want API Gateway to see that the data is not in the cache, let the first call through to my backend service while the other requests are held in queue, populate the cache from the first call, and then respond to the other 499,999 requests using the cached data.
What is (seems to be) happening
API Gateway, seeing that there is no cached value, is sending every one of the 500,000 requests to the backend service! So I will be recomputing the value with some complex db query way more times than resources will allow. This happens because the last call comes into API Gateway before the first call has populated the cache.
Is there any way I can get this behavior?
I know that based on my example that perhaps I could prime the cache by invoking the API call myself just before broadcasting the bulk push job, but the actual use-case is slightly more complicated than my simplified example. But rest assured, solving this simplified use-case will solve what I am trying to do.
If you anticipate that kind of burst concurrency, priming the cache yourself is certainly the best option. Have you also considered adding throttling to the stage/method to protect your backend from a large surge in traffic? Clients could be instructed to retry on throttles and they would eventually get a response.
I'll bring your feedback and proposed solution to the team and put it on our backlog.