Building a serverless food bank charity

In April I was furloughed for 3 weeks. To keep myself busy, I started a small community group called “Donate from Home”.

The idea was to help our local food bank increase their stock levels. The COVID-19 crisis was getting into full swing, and demand had significantly increased. At the same time, donations had decreased due to the closure of churches and stockpiling of food.

The idea was simple - we will collect donations from people’s doorsteps. At a high level, it worked like this:

  1. A Person signs up, providing an email address and collection address, and whether they will be donating on our next collection day
  2. On collection day, we download a list of addresses and plan the route
  3. We complete route and deliver to the food bank
  4. We send a thank-you email and ask people to sign up for next week (single button click in email)

We ran this for 10 weeks and had a significant number of donors each week - enough to make a substantial difference for our local food bank:


Our primary marketing channel was social media. We found local organisations and community pages to be incredibly helpful and supportive.

Technical

There were two primary factors when initially planning this initiative:

  • Time - the foodbank needed supplies ASAP, and I might be returning to work in 3 weeks
  • Ease of use - low friction for donors to sign up and opt into collections

On this basis, I selected the following technologies:

  • Mailchimp to deliver emails and act as our CRM system - storing all personal data
  • AWS serverless offerings (Lambda, API Gateway, S3 and DynamoDB) to support “click to opt-in” functionality

The high-level architecture looked like this:


Donors signed up on the site, which was hosted on S3 (behind a Cloudfront CDN), and had an embedded Mailchimp form:


Donors would then receive emails each week asking if they would like to donate. It was easy to opt-in - simply a button click:

Here’s how it worked:

  1. Collections were configured in a DynamoDB table
  2. The signup page would query this table via API Gateway, so new donors could see the next collection date
  3. Signing up would add the user to Mailchimp
  4. A scheduled lambda would generate JWTs for any user that does not have one, and then tag the user with “ready”
  5. Mailchimp would send a welcome email, triggered by the addition of the “ready” tag to a user
  6. Each week, an email asking people to opt-in to the next collection is sent. The JWT is embedded in the button links in the email
  7. Upon clicking the opt-in button, the user is taken to another lambda (via API Gateway), which validates the JWT and opts them into the collection (by tagging the user with collection-optin-YY-MM-DD), and then redirects them to a confirmation page
  8. After each collection, another lambda would run to re-generate all JWTs for the next collection. I would manually send out a thank-you email to everyone who donated

The overall cost of running this was $0.50 per month, which is the cost of a Route 53 hosted zone. We didn’t exceed free-tier limits for all other services (including Mailchimp).

Over time, I started to migrate email sending over to SendGrid as it’s more suited to transactional emails, however, Mailchimp was still used for CRM and one-off sends. This required another lambda and API gateway to keep user contact preferences in sync. Fortunately, both platforms provide webhook APIs, so this was relatively simple.

Everything was IaC’d in Terraform, so it was quick and simple to spin up test environments and make incremental updates to the infrastructure.

How it ended

The foodbank stock levels returned to normal over the following 2 months. This was thanks to the collective efforts of us and others who were working hard to get donations (for example, by setting up donation points in car parks).

As churches reopened, it became clear our efforts were no longer required to maintain the required stock levels, so we wrapped things up.

It was a great experience - I am grateful to my friends and family who gave up their time to review code and collect donations, and of course, everyone who donated.

Appendix: other considerations

  • Data protection: we were gathering personal data, so GDPR was in scope. There are various privacy policy templates online that helped, and the ICO site was useful in clarifying our responsibilities.
  • Charity Insurance: we were picking up donations from private households, so third-party liability insurance was necessary. We also had volunteers, so employer’s liability insurance is vital. And finally, as I’m paranoid about security, we also opted for data protection insurance. All in all it cost around £18 per month. The broker I used, PolicyBee, were great and highly recommended.
  • Car insurance: not all insurance companies cover driving for voluntary purposes. It’s important to check