Someone told me what I built at the hackathon wasn't a real backend. They weren't entirely wrong.
2026-05-16·6 min read
When I started learning backend development, the mental model was simple: you have a server, it runs your code, it talks to a database. Node.js, Express, a Postgres instance. Java with Spring. A process running somewhere, listening on a port, handling requests.
That model works. It's what most tutorials teach. It's what most bootcamp graduates know.
Then I built GOGuardian at TNG FinHack 2026 — a real-time AI fraud prevention layer for TNG eWallet — and someone told me what I built wasn't a real backend because I didn't write any server-side code.
They weren't entirely wrong. But they were thinking about the wrong thing.
what a traditional backend looks like
You write a server. It's a process. It starts, it runs, it handles requests, it talks to a database.
// classic Node.js Express server
const express = require('express')
const app = express()
app.post('/transactions', async (req, res) => {
const transaction = req.body
const result = await db.save(transaction)
res.json(result)
})
app.listen(3000)You deploy that to a VM or a container. It's always running. You pay for it whether it's handling requests or sitting idle at 3am doing nothing.
This is fine. For a lot of applications, this is exactly right. You have full control over the runtime, the environment, the execution. You can do anything.
The cost is operational overhead. You manage the server. You handle scaling when traffic spikes. You deal with the process dying and restarting it. You pay for idle time.
what we built at the hackathon
GOGuardian was a fraud detection system. A transaction comes in, it goes through a 3-layer inference pipeline — XGBoost for pattern matching, AWS Bedrock Nova Micro for AI analysis, a Groq Llama guardrail for final verification — and the system decides in real time whether to flag it.
There is no server in the traditional sense. There is:
- AWS Lambda — functions that run when triggered, shut down when done
- API Gateway — receives the HTTP request, triggers Lambda
- DynamoDB — handles the data storage
The backend is a set of functions, not a process. Nobody is listening on a port. There's no app.listen(3000). When a transaction comes in, Lambda spins up, runs the inference pipeline, writes to DynamoDB, returns the result, shuts down.
# AWS Lambda handler — no server, just a function
def lambda_handler(event, context):
transaction = json.loads(event['body'])
# run through inference pipeline
xgb_result = run_xgboost(transaction)
bedrock_result = run_bedrock(transaction, xgb_result)
final_result = run_guardrail(transaction, bedrock_result)
return {
'statusCode': 200,
'body': json.dumps(final_result)
}so is it a real backend?
The person who said it wasn't a real backend meant: you didn't write a server. You didn't manage a process. You didn't handle connection pooling or graceful shutdowns or any of the operational things that come with running a persistent server.
That's true. AWS Lambda handles all of that. You hand AWS a function and say "run this when something calls it." The infrastructure is abstracted away.
But the backend logic is still there. The data flow is still there. Authentication, validation, storage, business logic — all of it exists. It's just not inside a process you manage.
The trade is operational control for operational simplicity. You don't manage servers. You don't pay for idle time. You don't think about scaling — Lambda scales automatically. The cost is vendor lock-in and cold start latency and the mental shift of thinking in functions instead of processes.
what actually surprised me
The hardest part wasn't the cloud-native architecture. It was understanding the boundaries.
In a traditional backend, the request lifecycle is linear and visible. Request comes in, middleware runs, handler runs, response goes out. You can trace it.
In Lambda + API Gateway, the request lifecycle spans multiple AWS services. API Gateway receives the request and transforms it before Lambda sees it. Lambda's response gets transformed again before the client sees it. DynamoDB has its own consistency model. The AI services have their own latency profiles.
Debugging is different. You're not tailing a process log. You're piecing together CloudWatch logs across multiple services, correlating by request ID.
That's the real learning curve — not the syntax, not the AWS console. The mental model of how distributed systems fail and how you trace what actually happened.
which one is better?
Neither. They solve different problems.
Traditional backend: full control, straightforward debugging, works for anything, operational overhead is your problem.
Cloud-native serverless: zero operational overhead, scales automatically, pay per invocation, harder to debug, vendor dependent.
For a hackathon building a real-time fraud detection system that needs to handle unpredictable traffic spikes with an AI inference pipeline — Lambda was the right call. We didn't have time to manage servers. We needed to ship.
For a production SaaS with complex business logic, stateful connections, and a team that needs to debug things at 3am — a traditional backend might be easier to reason about.
The skill is knowing which one to reach for. That requires having built both.
I'm still building the traditional mental model — Express, databases, connection pooling, all of it. GOGuardian taught me the cloud-native side. The goal is to have both maps in my head so I can choose deliberately instead of defaulting to what I know.