All-in-one serverless DevOps platform.
Full-stack visibility across the entire stack.
Detect and resolve incidents in record time.
Conform to industry best practices.
Dashbird continuously monitors and analyses your serverless applications to ensure reliability, cost and performance optimisation and alignment with the Well Architected Framework.
What defines a serverless system, main characteristics and how it operates
What are the types of serverless systems for computing, storage, queue processing, etc.
What are the challenges of serverless infrastructures and how to overcome them?
How systems can be reliable and the importance to cloud applications
What is a scalable system and how to handle increasing loads
Making systems easy to operate, manage and evolve
Learn the three basic concepts to build scalable and maintainable applications on serverless backends
The pros and cons of each architecture and insights to choose the best option for your projects
Battle-tested serverless patterns to make sure your cloud architecture is ready to production use
Strategies to compose functions into flexible, scalable and maintainable systems
Achieving loosely-coupled architectures with the asynchronous messaging pattern
Using message queues to manage task processing asynchronously
Asynchronous message and task processing with Pub/Sub
A software pattern to control workflows and state transitions on complex processes
The strategy and practical considerations about AWS physical infrastructure
How cloud resources are identified across the AWS stack
What makes up a Lambda function?
What is AWS Lambda and how it works
Suitable use cases and advantages of using AWS Lambda
How much AWS Lambda costs, pricing model structure and how to save money on Lambda workloads
Learn the main pros/cons of AWS Lambda, and how to solve the FaaS development challenges
Main aspects of the Lambda architecture that impact application development
Quick guide for Lambda applications in Nodejs, Python, Ruby, Java, Go, C# / .NET
Different ways of invoking a Lambda function and integrating to other services
Building fault-tolerant serverless functions with AWS Lambda
Understand how Lambda scales and deals with concurrency
How to use Provisioned Concurrency to reduce function latency and improve overall performance
What are Lambda Layers and how to use them
What are cold starts, why they happen and what to do about them
Understand the Lambda retry mechanism and how functions should be designed
Managing AWS Lambda versions and aliases
How to best allocate resources and improve Lambda performance
What is DynamoDB, how it works and the main concepts of its data model
How much DynamoDB costs and its different pricing models
Query and Scan operations and how to access data on DynamoDB
Alternative indexing methods for flexible data access patterns
How to organize information and leverage DynamoDB features for advanced ways of accessing data
Different models for throughput capacity allocation and optimization in DynamoDB
Comparing NoSQL databases: DynamoDB and Mongo
Comparing managed database services: DynamoDB vs. Mongo Atlas
How does an API gateway work and what are some of the most common usecases
Learn what are the benefits or drawbacks of using APIGateway
Picking the correct one API Gateway service provider can be difficult
Types of possible errors in an AWS Lambda function and how to handle them
Best practices for what to log in an AWS Lambda function
How to log objects and classes from the Lambda application code
Program a proactive alerting system to stay on top of the serverless stack
In comparison to relational databases (RDBMS), DynamoDB requires a different approach to data storage and access patterns modeling.
RDBMS support ad hoc queries that are computed on demand, allowing for flexible access patterns. Usually, developers don’t have to think too much about how they will need to access the data in the future. This comes with a few disadvantges, though:
DynamoDB solves all these issues offering high scalability, fast and predicatable queries at any scale. It does require developers to think in advance about how data will need to be accessed later.
Adjusting DynamoDB to support different querying models later is possible. Nonetheless, this adjustment is usually more expensive in DynamoDB than developers are used to in an RDBMS.
The following items will cover strategies to enable flexible and advanced querying patterns in DynamoDB.
Consider a table that contains professional profiles (think of it as a version of LinkedIn). The base table’s primary-key is the user ID. People can be based in different cities. Retrieving all users based in New York, NY, USA, for example, would require a Scan, which is inefficient.
primary-key
A global secondary index[^1] can arrange users by the location attribute. In this case, the city, state, country values would become the primary-key in the index. Querying by primary-key == "New York, NY, USA" would return the results in a fast and efficient way.
location
primary-key == "New York, NY, USA"
A combination of attributes are commonly needed when querying. Following the example above, suppose the application need to query by location and employer. Say someone needs to retrieve all professionals based in New York, NY, USA that work for Company XYZ.
employer
A simple secondary index as outlined above wouldn’t be enough. There are two ways to support querying combined attributes:
Each item has a location_employer attribute whose value is the original attribute values concatenated. This artificial attribute is then used as the primary-key of a secondary index. The following query returns what the application needs: location_employer == "New York, NY, USA_Company XYZ".
location_employer
location_employer == "New York, NY, USA_Company XYZ"
DynamoDB does not build this type of attribute automatically. The logic to build and keep the location_employer attribute up-to-date must be implemented in the application backend.
Good programming practices must be followed in order to ensure data integrity. Especially DRY: there must be only one place within the application responsible for inserting and updating the user object data. Developers only have to worry about that part of the application to keep location_employer perfect and up-to-date.
Some programming languages offer features such as decorators and property objects. In Python, for example, it’s possible to create a user object that takes care of the artificial attribute by itself:
class User(): def __init__(self, user_id, name, location, employer, *args, **kwargs): self.user_id = user_id self.name = name self._location = location self._employer = employer self._location_employer = f'{location}_{employer}' @property def location(self): return self._location @location.setter(self, new_location): self._location = new_location # When a new location is set, it automatically updates the combined attribute self._location_employer = f'{new_location}_{self.employer}' @property def employer(self): return self._employer @employer.setter(self, new_employer): self._employer = new_employer self._location_employer = f'{self.location}_{new_employer}'
Instead of using a secondary index based on an artificial attribute, developers may also insert additional items to support combined attribute queries.
Consider a new user is being created:
{ 'primary_key': 123, // User ID 'sort-key': 1234567890, // Timestamp of user registration 'name': 'John Doe', 'location': 'New York, NY, USA', 'employer': 'Company XYZ' }
The following additional item is inserted in the same table:
{ 'primary_key': 'location_employer_New York, NY, USA_Company XYZ', 'sort-key': 123, }
Notice the primary-key pattern: it starts with what was the attribute name in the previous topic (location_employer), then concatenates the values for that particular user (New York, NY, USA_Company XYZ). The sort-key contains what is the User ID, serving as a reference to the original user item.
New York, NY, USA_Company XYZ
sort-key
When querying this table, the application can use: primary-key == "location_employer_New York, NY, USA_Company XYZ". One or multiple items are returned, it extracts the User IDs from the sort-keys and issue another read request to retrive the users information.
primary-key == "location_employer_New York, NY, USA_Company XYZ"
If the application is read-intensive, it might be a good idea to project (or copy) the entire user information in the additional items to spare the second read requests. This would increase storage space usage, thus should be thought carefully.
The same warning applies: the application must follow good practices – especially DRY – in order to keep additional items integral and up-to-date with the base user item.
When writing to tables following this pattern, it is highly recommended to wrap requests in transactions. A transactional query ensures that the user item will never be inserted/updated if the additional item failed to insert/update.
[^1] Refer to the Secondary Indexes page
No results found