You’ll recall from the last post that we’re working through Jeremy Daly’s 20 “easy” steps to switch from RDBMS to DynamoDB, using Babbl as our example application. In this post we’ll tackle steps one and two.

Step One

Accept the fact that can fit 90% of their retail site/system’s workloads into DynamoDB, so you probably can too. 🤔

Mind-blowing, but done. Fully mentally committed to this, otherwise why go through this exercise?

Step Two

Create an Entity-Relationship Model, just like you would if you were designing a traditional relational database. 👩‍💻

We’re going to make this a minimum viable product (MVP), so we can keep our entities as simple as possible while retaining the required functionality. We can get a functioning app with only four entities:

  • User
  • Conversation
  • Participation
  • Message


We’re going to hand off all the user authentication and storage tasks to Amazon Cognito. That way, all we have to worry about is:

  • username - (primary key) the username the user chooses at signup, to display in conversations
  • preferred_language - the user’s preferred language, for writing and reading messages. We will do this with a Cognito custom attribute, not the locale standard attribute


A conversation consists of two or more users sending and receiving messages. A conversation has the following properties:

  • id - (primary key) an automatically generated guid/uuid for identifying a single conversation
  • date_time_started - when this conversation was initiated
  • title - a plain text title field for the conversation


Since a user can join multiple conversations and a conversation can have multiple users, we have a many-to-many relationship. We model this with the participation entity. A single participation entity represents a single user participating in a single conversation, and contains:

  • user_id - (composite primary key, foreign key) the user’s username
  • conversation_id - (composite primary key, foreign key) the conversation’s id
  • date_time_joined - when this particular user joined this particular conversation


Finally, we can get to the heart of the app - messages! Since the whole purpose of Babbl is to allow multi-lingual chat, we would expect at least two rows to be created for every message sent: one for the original message, and one for the translated message. Rather than modeling these as two separate entities, we’re going to model them as a single, self-referencing entity with the following attributes:

  • id - (primary key) a guid/uuid unique to this message
  • original_message_id - (foreign key, nullable) the id of the original message from which this instance was translated, or null if this is the original message
  • sender_id - (foreign key) the username of the user who sent this message
  • conversation_id - (foreign key) the id of the conversation where this message was sent
  • language - the Amazon Translate language code for this message instance

When we wire up these four entities and their relationships, they look like this:

Entity Relationship Diagram showing four entities: User, Conversation, Participation, and Message

This is simplified, of course, but it’s enough for our MVP. We’ll modify this as we go along if necessary.

Next up - data access patterns.