Introduction
A while back I had the pleasure of building a product management portal for Mini & Mighty, a brilliant local coffee organisation run by some great people. If you’re in the area, do yourself a favour and pay them a visit.
I won’t be diving into the code itself, but the core problem they needed solving is one that a lot of small businesses face: their product data lived in multiple places, such as their online store, their accounting software, and more. Every price change or new product meant updating each system individually, which is not only time-consuming but surprisingly easy to get wrong when you’re dealing with hundreds of SKUs.
The portal became their single source of truth, one place to manage everything.

Balancing Cost and Benefit
Working with SMEs brings a specific challenge that you don’t always encounter in larger organisations: every pound spent needs to be justified. I started my career in IT support at a Managed Service Provider, so I’ve seen first-hand how quickly hosting costs can become a blocker, even when the technical case is solid.
Mini & Mighty were refreshingly pragmatic about it, but I still wanted to keep the running costs as lean as possible. As a developer, it’s tempting to reach for all the usual trappings: Docker, microservices, separate staging and production environments. Those decisions carry real cost, and for a project like this, most of that complexity would go unused. That’s a solution you grow into and it can’t just be a benefit to the developers working on it.
The Solution
The stack leans on AWS services (largely within the free tier) alongside Vercel for hosting the portal itself.
Authentication is handled by Auth0, which at this scale is cost-effective and integrates cleanly with Next.js. The rest of the architecture sits within AWS.
Product data is stored in DynamoDB, kept up to date by a scheduled Lambda that syncs from their external stores. The portal itself only has read access to that data. Writes go through a separate, controlled process.
For bulk product management, users upload CSV files directly in the portal. There’s client-side validation against a set of templates to catch issues before anything hits the backend.

Once a file is submitted, it’s placed (along with some metadata) into an S3 bucket. That upload triggers a Lambda to parse the file into manageable chunks, followed by another Lambda to process each chunk of data, updating both DynamoDB and the external product stores.

The design is deliberately straightforward. The whole thing lives in a monorepo, with GitHub Actions handling deployments to both Vercel and AWS via the CDK. Vercel takes care of itself but the AWS CDK makes the AWS side just as easy to wire into a CI/CD pipeline.
Every step in a product’s journey is logged back to DynamoDB, giving the team full visibility over what changed and when.

The high-level architecture is shown below. Some parts have been simplified, particularly around how code is shared across services, but it gives a clear picture of how everything fits together.

With Mini & Mighty’s permission, I’ve shared this to illustrate that well-architected solutions don’t have to be expensive. Could I have spun up an EC2-hosted API with cleaner separation of concerns? Absolutely. But this solution is actively used, stays well within its constraints, and the team manages it largely on their own, which was always the goal.