Serverless For the Simple-Minded (Like Me)
A lot of features in Harmonize are powered by serverless functions.
As a self-taught software developer, I’ll admit that the idea of “serverless” confused me for a long time. After working (and wrestling) with them for a while, I’ve developed a clearer understanding of what they actually are — and the tradeoffs they introduce.
To start, it helps to define what a server actually is.
A server is simply a program running on a computer that listens for incoming requests, performs some kind of task, and returns a response. Importantly, this program is always running. If it stops, even for a moment, it can’t receive new requests or do any work.
This is what we might call a server-full model. The program never sleeps.
In this model, a server waits in the background, ready to handle tasks — “functions” — the moment another computer asks for them.
Serverless: Same Idea, Different Assumptions
Serverless functions follow the same core idea (a request comes in, a task is performed, a response is returned), but with one major difference:
Serverless functions do not run continuously. They wake up only when needed.
A helpful analogy:
Imagine a restaurant that is normally closed.
When you knock, the lights turn on, the staff appears, and the kitchen fires up.
As soon as your meal is finished, everything shuts down again.
This is great for cost efficiency — you only “pay” to run the restaurant when someone shows up.
But it introduces logistical quirks that traditional servers don’t have.
The Hidden Limitation: Work Stops When the Response Sends
Here’s the key detail most beginners miss:
Once a serverless function returns its response, it immediately shuts down — even if background work is still running.
And this is exactly the issue we ran into with Harmonize.
How Harmonize Handles an Incoming Text
When a user sends a text message to Harmonize, our inbound serverless function performs three tasks:
- Log the message in our database
- Trigger a background job that parses the text and converts it into structured data
- Send a confirmation text back to the user
The problem?
Tasks 1 and 2 sometimes take longer than task 3.
So the moment task 3 completed — when the confirmation message was sent — the serverless function assumed its job was done and shut itself down.
Tasks 1 and 2 were still in progress.
But the function was already gone.
Result
Some test messages weren’t being logged or processed at all.
How We Fixed It
To fix this, we introduced guardrails to ensure that:
- the database write
- and the background job trigger
both complete before the serverless function responds to the user.
Only after those critical steps succeed do we return the confirmation message.
This ensures zero data loss and a fully reliable SMS ingestion pipeline.
Closing Thoughts
It’s a small technical detail, but just one of many we obsess over to make Harmonize feel seamless. Our goal is for the experience to feel like working with a trusted coworker — someone who understands your workflow, keeps your data organized, and quietly handles the complexity behind the scenes so everything “just works.”