Headed to QCon 2024 in San Francisco? Book a meeting with us!

Boost your stats with our new increment API

Real-time counts and rate limiting have never been easier.

Allen Helton
Author

Share

Momento has been on a roll lately with a slew of new cacheable collection data types including dictionaries, lists, sets, and sorted sets. These data types add tremendous value on top of the classic get and set functionality of Momento Cache and open up great new practical use cases which we’ve been using to build our game, Acorn Hunt. These use cases include dictionaries to store player metadata, sets to store lists of unique players in each game, and lists to manage in-game chat

On top of all that, we’ve built a leaderboard with sorted sets giving us a hands-free way to track individual player scores without writing any complex logic of our own.

Today, we’re announcing a new feature that continues to extend our use cases and enable more features in Acorn Hunt: the increment API.

What does it do?

This function does exactly what you might think: increases (or decreases) a number by a given amount and returns the result. It might not seem like it on the surface, but let me tell you why this is a big deal for Momento Cache.

Our remote, centralized cache is built for use in distributed systems, where multiple requests come in for the same resources simultaneously. This could create a problem when two callers try to update the same resource at the same time.

For example, in Acorn Hunt, we need to update the total number of acorns collected by all players in a game. If two players gather acorns at the same time, we might end up with the wrong score if the software workflow is to get the current score, add a point (in application memory), and then save back the updated value by overwriting whatever is there. What if there has been another update stored in the meantime?

Fear not, my intrepid acorn hunters! By using the increment API, we can avoid this issue entirely. Instead of fetching the current score and updating it, this API simply accepts a value representing the amount of change, applies it, and returns the resulting number. No errors or debugging headaches—an API call that “just works”.

What can you do with the increment API?

There are many good use cases for our new increment capability. Any scenario where you need a counter or rate limiter can be handled with this new feature. Let’s take a look at Acorn Hunt for some practical examples.

Track game statistics

Like I mentioned earlier, we use this new functionality to track stats like the number of acorns gathered in a specific game. This number is updated by all the players of a game, so the API eliminates contention on the score resource and guarantees it is always right. 

Imagine an endpoint that updates the score with a provided value.

#
# POST /games/{gameId}/points
#
def lambda_handler(event, context):
  momento = getCacheClient();
  gameId = event['pathParameters']['gameId']
  body = json.loads(event['body'])
  response = cache_client.increment('acorns', gameId, body['points'])
  return {
      'statusCode': 200,
      'body': json.dumps({'score': response.value})
  }
}

The beauty about the increment call is that you can provide any number, positive or negative, as long as it is an integer. This means whole numbers, no decimal points!

A Better Rate Limiter

In our post on sorted sets, I provided a use case for rate limiting super-ability usage in Acorn Hunt. While it technically works with sorted sets, the increment API is a cleaner, lighter-weight solution. Consider this implementation of a rate-limited endpoint:

#
# DELETE /games/{gameId}/super-ability
#
def lambda_handler(event, context):
  momento = getCacheClient();
  gameId = event['pathParameters']['gameId']
  username = event['requestContext']['authorizer']['username']
  response = cache_client.increment(f'{gameId}-super-abilities', username, -1)
  if(response.value < 0):
    return {
      'statusCode': 409,
      'body': json.dumps({'message': 'Out of super-ability uses'})
    }
  else:
    return {
      'statusCode': 200,
      'body': json.dumps({'remaining': response.value})
    }
}

This endpoint will decrement the ability count for a player by 1 and whenever a negative number is returned, it will throw an error. It is a much simpler solution than the one we had before!

Ready to build?

Starting today, the increment API is available in our newly minted Python SDK. Get started with stat tracking, rate-limiting, and counting everything imaginable with a single API call. 

Not a Python user? Stay tuned—increment support is coming to our Node.js, .NET, Java, PHP, Ruby, Go, and Rust SDKs soon!

Do you have a cool use case for the increment API? Share it with us on Discord! We would love to see what you build and help you work out any ideas you come up with.

Share