Sellflow Rewards is a passion project of mine meant to solve the problem of needing a backend for a Shopify mobile app. I initially set out to make a mobile app, however I didn’t want another toy project that only sat as a git repo and went nowhere. I wanted a real production app, then it hit me, my mom has a Shopify store. So I began working on the app, then realized that in order to receive notifications or get her loyalty rewards points like she wanted, the app needs a backend. This is what led me to where I’m at, currently working on a Shopify app to serve as a backend for mobile clients which, in theory will simplify app development and mostly remove the need for a backend.

Who the heck am I?

I’m a nineteen year old self-taught developer, currently working a full-time job as a [redacted]. I’ve been programming for a little over 4 years now, I began my CS journey with Harvard’s CS50 which gave me a great foundation to build on. This was apart of OSSU (Open Source Software University) which I’m still working through, I’m a hyper-focused person, so working on an app and learning the math required for this in the little free time I have after work or during the weekend; simply doesn’t work for me. What does work however, is reading, whenever I can find time to read a book I can usually finish it over a weekend and instantly apply what I learned to what I’m currently working on. Now the hope is that I can work through the rest of OSSU once I make enough money to quit my full-time job and start my own business. While this may sound counterintuitive as I will presumably have less time while running my business (it probably is) that’s the hope anyway.

I’m starting this weekly blog, because I love open source software, not just for what is provides such as awesome databases (such as PostgreSQL), or orchestration tools like Kubernetes; but for the people and ideas which built those awesome things. Knowing that PostgreSQL was built at MIT to solve the problem of SQL databases not being extensible enough to handle various applications outside of transactions hence its rich extension ecosystem, is awesome. Which is why I’m building in the open to share my thoughts, ideas and progress on my app, just in case I create the next Linux or something.

Original Architecture

Project Requirements:

The app requires the backend which receives requests received from the admin panel which store owners use to manage our apps settings. This same backend needs to receive and authenticate Webhook requests which are then sent to the webhook handler service.

Services:

  • Admin backend

  • Webhook handler service

  • API Gateway

  • Kubernetes Cluster

  • Kafka

  • Postgres

Now I am aware this is terribly overkill for an app which I expect will have less than 10,000 users. However, it’s really just because I wanted to learn about technologies used in real production environments. Below is the diagram I created for the architecture I originally wanted.

I wanted to try out the microservices architecture just to see what it was like and it was my understanding at the time that microservices worked best with an API Gateway. So I decided to go with APISIX which sounded right as gateways are essentially load balancers with extra features like authentication, consumer groups (for plan based rate-limiting) and well that’s really it but it sounded cool at first.

In theory, the gateway would authenticate requests before they hit my microservice, pass the authenticated user ID to my service, then easy peezy. What I soon realized was most API gateways are expensive and lock every useful feature behind a paywall. For example, I wanted to use a specific claim for a given JWT to identify users, this was either locked behind a paywall or the documentation was just terrible.

On top of that terrible decision, I decided on Kafka for event streaming, I feel that this one was justified however as it doesn’t make sense for Shopify’s Webhook to wait on a response from my server while processing the Webhook. Now I could’ve used Redis to create a queue with something like BullMQ, but to me Redis just doesn’t seem reliable enough, the idea of dropping an event for a users $200 order and not rewarding them points is not something I want to deal with. In my mind I needed a durable queue (well I still believe I do just not Kafka.)

The final screw up in my long list of mistakes was essentially wanting to create my own server-less infrastructure. The idea was to have a Kafka cluster in three regions across the globe which I would use Cloudflare’s Geo-DNS to route requests to based on the users proximity to each server. Again this isn’t because I’m expecting 2 million users day one, it’s just because I wanted to learn what it’s like to work with various technologies, but it simply requires to much time and I want to actually finish this app. I may have gotten in a little over my head with all of the features I thought I could implement by myself while working on this in my free time.

Takeaway

My biggest realization after tinkering with all of these technologies was that for each service you add to your project it isn’t just spinning up that service that comes with it. Tech debt is absolutely a thing and for every service I added to my architecture, comes a new client to interact with a service, a new configuration file to manage, possibly a new volume to manage. Not only this, you now have to build around whatever services you add to your stack and work around its quirks.

Postgres is AWESOME

I do want Kubernetes

While Kubernetes is absolutely overkill and I could 100% run everything on a single VPS with Coolify or Dokploy. Kubernetes still intrigues me, so I’m using LKE (Linode Kubernetes Engine) to run and manage my app.

PostgreSQL is more capable than you think

In my eyes the app still does require a queue of some sort of queue to quickly queue Webhooks for later processing. After reading the book Just use Postgres I realized Postgres is more capable than I thought it was. The extension pgmq is a lightweight extension on top of Postgres which allows it to act as a simple message queue with advanced features like topics. Postgres’ architecture makes it inherently durable, so I don’t need to worry about dropping an event. This also removes the need to manage a separate service as I’m already using Postgres.

Background Services

I don’t think I’m doing full blown microservices, but correct me if I’m wrong. I still have separate services for Webhook and notification handlers, which read events from pgmq.

TimescaleDB

Originally I decided on Citus since I thought sharding Postgres would be cool (it would be.) The problem for me was this required more manual configuration than I wanted, while this could’ve easily been implemented with a couple of cron jobs. It is just much simpler with TimescaleDB which automatically partitions your tables for you, provides continuously updated materialized views. This is perfect for my customer facing analytics dashboard.

All in all, I’ve learned a lot working on this project and still have a lot to learn. I hope you learned something from this post. Let me know if you like this format of me mixing my personal ideas and thoughts into this post or if you’d like a purely technical point of view.

Reply

Avatar

or to participate

Keep Reading