Primeversary Emailer: Part 1
I recently built a tiny service to email my (future) wife and I when we’ve been married a prime number of days!
Why build a primeversary emailer service?
Because prime numbers are really cool! There are infinitely many of them, but predicing when the next one will be isn’t solved. After about a month, we will have no idea whether it’s been a prime number of days or not, so the emails will always be a bit of a romantic surprise.
How does the problem break down?
There are a few things that need to happen for this to work:
- Run some code every day (only running on the prime days seems beyond what
cron-like tools can do, since it’s more complex that you can put in a cron string)
- Check whether that day is a prime number of days since we got married
- Send an email if it is
Since part of my goal is getting more fluent with AWS, I’m going to use AWS to solve each of these problems.
Overall tech stack
The overall tech stack for the primeversary emailer service is:
- An AWS CloudWatch Rule that triggers about 5 AM every day.
- A step function that is triggered by the cloudwatch fule
- A lambda that checks whether it’s been a prime number of days (this was the really fun part; stay tuned).
- An SNS topic we publish a notice on if it has been a prime number of days.
Why use step functions? Why not do the whole thing in a single lambda?
This was my first project using AWS Step Functions, and they’re great, but when I initially conceived the project, I planned to write a single, longer lambda that would decide whether to send the email or not, and actually send the email, but decided to try out step functions instead.
I think the key benefit to step functions is that you can define things at two levels of detail, but you only have to write real code for one of them. For example, in this case we have basically two pieces of code:
ifstatement that sends an email if a condition is true
- A method that computes the number of days between two dates, and decides whether that number is prime.
The second of these two rules obviously requires a real programming language - no one makes “is it a prime number of days as a service.” But the first rule? Check whether a value is true and if so send an email? That’s much simpler, more flow-charty logic.
And this is the real benefit of step functions. A lot of code needs to be concerned with actual bytes; it needs to do real math or complex logic, and you need a full-featured programming language to express it at all. But a lot of code does things like “publish this JSON on this SNS topic” or “run this CodeBuild job” or something. And that stuff is all configuration; publishing to an SNS topic is just about getting the right body and the right ARN for the topic. Calling the SDK from a fully featured programming language doesn’t really get you anything that using a step function integration doesn’t.
I think this is the general approach I would take to new serverless workloads: Run a step function for the overall business logic, and drop into lambdas whenever you have something that can’t be written down in a fairly simple flow chart.
Next time, we’ll take a look at the actual step function I built, and the following post we’ll look at the lambda in detail.
Till then, happy learning!