Following that is the real meat of the API, the EventsAPI resource (line 257). This defines the Authorizer to use, the HTTP method (POST, line 265), and then the really interesting part, the VTL template, RequestTemplates, that maps the incoming JSON to a DynamoDB request:
It was bad timing to raise money because we didn’t know what we were doing. We didn’t have a product and we didn’t have any revenue. Fast forward to today, however, and we have a product with close to €20.000 in monthly revenue. But regardless of this, we still ended up saying no to an investment. The primary reason for this is because it is still too early and we aren’t quite there yet.
The post-processing we do takes longer and is fairly involved, and thus I wouldn’t want that being done synchronously on receipt of each of these events (nevermind on a batch of 25 events). Therefore, this architecture creates a very simple API that just worries about storing the raw data. Clients either get the format of that data right or they don’t, which is about the only error they can get from the API. Then later, we process these events (which is more time consuming).
The TimeUTC element (line 284) is a string (in DynamoDB) and the incoming JSON already has it as standard ISO format so it can just be set directly like this. It is used as the Sort Key in this table, so having it in ISO format makes it properly sortable.
Lastly, a subtle one. Note the code #if($foreach.hasNext),#end(line 293). That’s a way to add the trailing comma in after each item in the batch of items for the DynamoDB request. Dynamo is particular though, and does not allow a comma after the last item, which is why we have this wrapped in the conditional (i.e. only add the comma if there will be more items after it). Without this, DynamoDB will fail your request.
After that comes the IntegrationResponses and MethodResponses . These were a little confusing and unclear on how to set up at first. The IntegrationResponses handles the proxy/request to Dynamo, and is mapping its responses for API Gateway, which then get mapped to the MethodResponses which API Gateway uses for the actual HTTP response.
People can help you scale what you are doing well and what works. But if you don’t know what you are doing, it will take you more time aligning a team. of 14 people than it would have taken to do the job alone. Not to mention that it’s super expensive
A VTL foreach loop (line 279) is used to iterate over the incoming list of events, and map each one to a PutRequest. Note that the incoming events are just a simple JSON array/list of single level of attributes, but if they had nested elements, you’d just use this same dot syntax to traverse deeper as needed.
The user’s Cognito ID can be extracted from the $context.authorizer.cliams.sub element (line 283). But, as you can see, this is inserting additional data for DynamoDB that wasn’t part of the original HTTP request’s JSON, as well as showing how to get to the Cognito data.
You may be thinking — wait, you said we eliminate the need for a Lambda, but now you have one doing the post-processing. True! But you may or may not need that step, AND, the key here is that you are avoiding doing potentially time consuming processing during the API call (thus creating a slow/long response time for your API). Furthermore, with the streams API, you can fetch up to 1000 records for a single Lambda invocation (vs the limit of 25 on the incoming/batch write aspect). Therefore, you potentially could have 40x fewer Lambda invocations (if you can process all 1000 records in the 15 minute Lambda time limit). That said, the real key here for me was not doing the heavy processing we do during the API call, keeping the API itself very fast and having the fewest possible error scenarios.
We got community managers, marketing managers, sales managers, and all kinds of developers. We spent time designing the job description, marketing those, selecting people, onboarding them. It is a very straightforward task to do when you are a stable company. But when you don’t know what you are doing, have any revenue, and changing the direction every week, it is the recipe for disaster. Employees are not founders. They need direction and they can’t adjust every week. Even for founders it’s super hard and takes me as the CEO several discussions with the team.
The rest of the elements are just a straight mapping from the incoming JSON to the value for the DynamoDB attribute. Note that of course you can have different names for the DynamoDB attributes vs. the JSON attributes, such as sensor_name gets stored as Sensor in DynamoDB.
The RequestItems (line 277) is the root element of a DynamoDB BatchWriteItem operation. As mentioned above, you can have at most 25 individual requests within this (these can be different, e.g. you can mix Put and Delete, although for this obviously we’re only doing PutRequest items). We’re obviously not enforcing this batch size limit here, which is one downside — you’re having to rely on your clients who call this to behave properly. When you do send more than 25, the Dynamo request will fail, and it’ll fail the API Gateway call/return an error. This is something to consider when doing these proxy style API’s, as you clearly get less in terms of how you can handle errors and how you might want to respond in such a case. I believe there is likely a way with the VTL template to potentially map it differently, or maybe immediately return an error if the count of items is higher, but I haven’t explored that yet.
While not required, as mentioned early on, I am doing asynchronous post-processing of these incoming events. This is handled via DynamoDB’s streams. This setup involves a Lambda function that listens to the DynamoDB stream which provides all events from Dynamo (insert, delete, update, etc.). Thus, in my case, for this post-processing, you do need to filter to just INSERT events.
- Citrix Virtual Apps and Desktops 7 Advanced Administration are a major upgrade of Citrix NetScaler 6. Advanced Administration is also one of the most important upgrades to the product.