We were unable to load Disqus. If you are a moderator please see our troubleshooting guide.

suanik • 3 years ago

What is the point of having both a PartitionKey and a SortKey in your example "Maintaining uniqueness on multiple attributes", as both values are identical ? Why not using just a PartitionKey ?

Alex D • 3 years ago

I almost always use a composite primary key in case I do need it for one of my entities. That said, if I knew I would only have a single entity type in this table and that I'm not doing any grouping by the partition key, a simple primary key would work as well. Good question :)

Abhishek Gupta • 5 years ago

In "Handling counts and preventing duplicates" section wouldn't the first request in the write transaction check the existence of SK instead of PK to see if the user has commented on the given post earlier?

Alex D • 5 years ago

Good question, Abhishek Gupta , and it's one that trips up a lot of people.

When you do a attribute_not_exists ConditionExpression on an element of the primary key, it checks to ensure the exact primary key does not exist. It doesn't matter whether you use the PK or the SK in your expression.

Kind of confusing but it works either way :)

Abhishek Gupta • 5 years ago

Got it. Thanks Alex, learning a lot from your blog :)

Alex D • 5 years ago

Glad to hear it! :)

Ross Williams • 5 years ago

Great content, very useful in understanding how to insert data into an existing structure. What keeps me from using NoSQL more is mutating data. With relational 3NF changing a user’s email address is trivial, but the demornalisation in this post worries me in terms of development time / cost, and potential for mistakes, especially as the app grows larger. Would love to see content on mutating denormalised data as a follow-up, or is it just a case of being very careful and doing daily batch “cleanup” scans?

Alex D • 5 years ago

Thanks, Ross Williams ! And good point. I've had more people asking me about mutations and updating data. I'll be working on some thoughts around that in the near future :).

Stefan • 1 year ago

I really like your DynamoDB series. I have one issue with transactions: At least in the AppSync integration (and it looks in boto3 as well, so I assume it is a general restriction of the API) you don't get item level information back on the items that you touched inside the transaction. This may not be relevant for inserts where I already have all the information available, but relevant for updates and deletes where I don't know the current attributes.

In the "post has comments" example let's assume admins can delete posts that don't have upvotes. You may want to run a transaction like this:
- Condition check in your access control table for the current user
- Delete post with the condition that the post's current upvote counter is zero

There does not seem to be a way to provide the caller with the actual post that was deleted (despite the key attributes). I feel that this heavly restricts the usefulness of transactions or do you have other experiences?

Samuel Laferriere • 4 years ago

In "Maintaining uniqueness on multiple attributes", why are we not writing the emails to a separate emails table? It seems that transactions can write to multiple tables.
I know that you recommend single-table design, but in such a case, it seems that it doesn't actually have any benefits and will just globber up the table and make it harder for new devs to realize that there's "hidden" information inside the table no?

Jim Ancona • 5 years ago

I'm using TransactWriteItems with a ConditionCheck to check a foreign key constraint. So I have two items in my transaction, the ConditionCheck, which checks for the existence of a parent item in the table, and a Put, which inserts a child item, which contains an attribute that references the parent. When I concurrently insert multiple children that all reference the same parent, I often get a TransactionCanceledException, where the CancellationReason is "TransactionConflict" and its position in the array corresponds to the condition check. As far as I can tell, the parent item isn't being written to concurrently. Is there some other reason I would be getting a conflict in this situation?

Alex D • 5 years ago

Hey Jim Ancona, that's interesting that it appears to be the ConditionCheck that's failing. Is the item being checked one that's often written to in other operations? Here are the reasons a Transaction can fail, and most are when one of the items is being affected in another operation. https://docs.aws.amazon.com...

Jim Ancona • 5 years ago

Thanks for the reply, Alex D ! I've checked my logs, and the last write to the parent record appears to be more than 100 milliseconds before the failure. So I'm kind of at a loss. I've implemented retries as a workaround, but it seems odd that a simple existence check would fail in this way.

Karl Möller • 3 years ago

Hi Jim Ancona did you ever figure this out? I am seeing the same, my ConditionCheck singleton is definitely not getting updated/written to.

AdamH • 5 years ago

Thanks for this writeup. I have a question about the example provided for"Handling counts and preventing duplicates." Since the behavior of TransactWrite is to return an error "if one of the items is being altered in a separate transaction or request" then I'm wondering if the Update code where we increment a Post's UpvotesCount will generate transactional errors when one Post item receives multiple concurrent upvotes from multiple users (because they all attempt to update upvotesCount for the same Primary Key)? If my understanding there is correct, is there a good pattern to use to handle this scenario?

Alex D • 5 years ago

Hey AdamH ! Good question. That could happen, which would mess with your flow. One other pattern is to do your aggregations after the fact, such as hooking up to DynamoDB Streams and incrementing the UpvotesCount after the fact. This would ensure the Upvote succeeded without potentially blocking other transactions.

Henrik Dohlmann • 5 years ago

Very useful information!
For the count example, how would you model: Top upvoted posts the user has voted upon?

I have thought about something with PK=USER, SK=<count>#POST to be able to perform the query.
When the UpvotesCount is updated on a post, I then need to write UpvotesCount#POST to an attribute on the PK=POST, SK=USER for all users that voted on that post.

Is that feasible? Or, should I do something else?

Alex D • 5 years ago

If I'm understanding correctly, that's a pretty tricky one. You have a many-to-many relationship you're handling (each post can have many likes, and each user can like many posts). Additionally, the information you want in mutable (a running count of likes for the post).

It would require a lot of updates each time someone upvoted a post...

Henrik Dohlmann • 5 years ago

Precisely. That is why i asked :-)
I don't know if aggregate-on-write makes sense here, or if I should have a batch-job that adjust counts for each user.
Or, if there is some NoSQL pattern for this that I haven't read about yet.

Guest • 5 years ago
Alex D • 5 years ago

Glad you liked it!

There's no real reason :) You could use either one to check. Good question!

Chris Shenton • 6 years ago

I didn't think I needed/wanted transactions. Your article convinced me otherwise. Thanks!

Alex D • 5 years ago

Glad to hear! :)