Amazon Kinesis & AWS Lambda Retries

Stefano picture Stefano · Sep 10, 2015 · Viewed 17.4k times · Source

I'm very new to Amazon Kinesis so maybe this is just a problem in my understanding but in the AWS Lambda FAQ it says:

The Amazon Kinesis and DynamoDB Streams records sent to your AWS Lambda function are strictly serialized, per shard. This means that if you put two records in the same shard, Lambda guarantees that your Lambda function will be successfully invoked with the first record before it is invoked with the second record. If the invocation for one record times out, is throttled, or encounters any other error, Lambda will retry until it succeeds (or the record reaches its 24-hour expiration) before moving on to the next record. The ordering of records across different shards is not guaranteed, and processing of each shard happens in parallel.

My question is, what happens if for some reason some malformed data gets put onto a shard by a producer and when the Lambda function picks it up it errors out and then just keeps retrying constantly? This then means that the processing of that particular shard would be blocked for 24 hours by the error.

Is the best practice to handle application errors like that by wrapping the problem in a custom error and sending this error downstream along with all the successfully processed records and let the consumer handle it? Of course, this still wouldn't help in the case of an unrecoverable error that crashed the program like a null pointer: again we'd be back to the blocking retry loop for the next 24 hours.

Answer

az3 picture az3 · Sep 11, 2015

Don't overthink it, the Kinesis is just a queue. You have to consume a record (ie. pop from the queue) successfully in order to proceed to the next one. Just like a FIFO stack.

The appropriate approach should be:

  • Get a record from stream.
  • Process it in a try-catch-finally block.
  • If the record is processed successfully, no problem. <- TRY
  • But if it fails, note it down to another place to investigate the reason why it failed. <- CATCH
  • And at the end of your logic blocks, always persist the position to DynamoDB. <- FINALLY
  • If an internal occurs in your system (memory error, hardware error etc) that is another story; as it may affect processing all of the records, not just one.

By the way, if processing of a record takes more than 1 minute, it is obvious you are doing something wrong. Because Kinesis is designed to handle thousands of records per second, you should not have the luxury of processing such long jobs for each of them.

The question you are asking is a general problem of queue systems, sometimes called "poisonous message". You have to handle them in your business logic to be safe.

http://www.cogin.com/articles/SurvivingPoisonMessages.php#PoisonMessages