Role 5: Backend Developer
Writes the logic, business rules, and integrations that power everything the user sees.
The Excel Analogy
Of all seven roles, the Backend Developer role maps most precisely to something CA professionals use every day. Every complex formula, every VBA macro, every cross-sheet calculation you have ever written is backend logic.
The raw data sheet exists. The formatted client-facing sheet exists. But something has to connect them and do the actual work.
That is the formulas. The VBA macros. The data connections that pull exchange rates from an external source. The VLOOKUP that combines client names with their invoice totals. The conditional logic that flags invoices overdue by more than 30 days. The macro that sends an email when a certain cell changes value.
None of that is visible to the client. It is all happening behind the scenes. It is the intelligence layer that makes the spreadsheet useful instead of just pretty.
In software, the Backend Developer builds this intelligence layer. It lives on a server (in our case, Supabase), not in the user's browser. It processes requests from the frontend, applies business rules, reads and writes to the database, and talks to external services (payment gateways, SMS providers, email services, mapping APIs).
What This Role Builds
Database queries — reading and writing data:
- "Give me all fee records for this student, sorted by due date, that are still unpaid"
- "Mark this attendance record as present, and record which teacher marked it and when"
- "Find all students in Branch A whose fees are overdue by more than 30 days"
Business rules — logic that enforces how the application works:
- A teacher can only mark attendance for students in their assigned class — not another class
- Attendance cannot be marked for a future date
- A fee record cannot be marked as paid unless a valid Razorpay payment ID is provided and verified
- A student cannot be enrolled in a class that belongs to a different branch
Edge functions — serverless code that handles specific tasks:
- Create a Razorpay payment order when a parent initiates fee payment
- Verify the Razorpay payment signature and mark the fee record as paid
- Send SMS reminders to parents of students with overdue fees — runs on a schedule
- Generate a result card PDF for a student after results are entered
Integrations — connecting to external services:
- Razorpay: fee payment processing (UPI, card, netbanking)
- MSG91: SMS reminders for overdue fees and exam notifications
- Resend: transactional email — fee receipts, result notifications, enrollment welcome
The Supabase Mental Model
We use Supabase as our backend. Supabase gives us:
| Supabase feature | What it does | Excel analogy |
|---|---|---|
| PostgreSQL database | Permanent, structured storage | The raw data sheet |
| Row Level Security (RLS) | Rules about who can read or change each row | Sheet protection with user-specific permissions |
| Auth | Login/signup, session management, user identity | The username/password that unlocks protected sheets |
| Edge functions | Custom server-side code for business logic | VBA macros that run on the server, not your machine |
| Realtime | Live updates when data changes | Like a Google Sheet that updates for everyone immediately |
| Storage | File storage (images, PDFs, documents) | A shared network drive linked to your data |
When you write a backend query, you are writing instructions like:
In English: "From the fee_records table, give me all columns, also include the student's name and class, but only for rows where the branch_id is this admin's branch and the status is overdue, sorted by due_date oldest first."
This is readable. You do not need to memorize the syntax — Claude writes it. You need to understand what it is doing well enough to check that it is correct.
Business Rules: The Most Important Backend Concept
Business rules are what makes your backend more than a database wrapper. They are the logic that makes your application behave correctly for your specific business.
Example — the duplicate attendance rule:
A teacher marks Class 7B's attendance for Monday. Later that day, a second teacher (a substitute) tries to mark attendance for the same class and same date. This must be prevented — you cannot have two attendance records for the same student on the same day.
The frontend cannot reliably enforce this (it does not know what was already submitted). This logic must live in the backend — in a database unique constraint or edge function that checks for existing records before accepting a new batch submission.
Example — the fee amount rule:
The fee amount for a student is not a number the parent sends to the server. It is calculated from the fee_structures table based on the student's grade and branch. When a parent initiates payment, the backend reads the fee amount from the database itself — it does not trust whatever amount the parent's app sends.
This calculation lives in the backend. If a parent's device is tampered with and sends a lower amount, the backend ignores it and uses the correct amount from the database. Business rules live in the backend.
Never trust data sent from the frontend. A parent's app tells your backend "the fee amount is ₹500." Your backend should not accept that. Your backend should look up the fee amount itself from the fee_structures table and ignore any amount sent from the client. This prevents parents from manipulating payment amounts — or any other business-critical value — by modifying what their app sends.
When You Are in This Role
Put on the Backend Developer hat:
- When you are writing Supabase queries (
.from().select().eq()) - When you are writing edge functions (code that runs on Supabase's servers)
- When you are defining business rules that govern how data can be changed
- When you are integrating with a third-party API (payment, SMS, email)
- When you are writing database functions or triggers
- When you are thinking about what happens when two users do something simultaneously
Common Mistakes When You Skip This Role Properly
Business logic in the frontend. Fee amount calculation, sibling discount eligibility, attendance deadline checking — these land in the React component "for now" and never move. The frontend is easy to manipulate. Any logic that has security or financial implications must live in the backend.
No input validation on the server. The frontend validates the form (required fields, phone number format). The developer assumes that is sufficient. An attacker bypasses the frontend entirely and sends a malformed request directly to the backend. Your backend must validate every input it receives, independently of whatever the frontend does.
N+1 queries. The branch admin dashboard loads a list of 30 students. For each student, it makes a separate database call to get their latest fee status. That is 31 database round-trips to render one screen. The correct approach: join the tables in one query. This is a backend design problem, not a frontend problem.
No error handling in edge functions. An edge function calls the Razorpay API to process a fee payment. The API is temporarily unavailable. The function crashes with an unhandled error. The parent's payment is not processed, but the app shows no useful error. The database record is in an inconsistent state. Backend code must handle every error case explicitly — with retries, fallbacks, and clear logging.
Storing secrets in the wrong place. The Razorpay Key Secret is needed to verify payment signatures. A developer puts it in the frontend React code "because it is easier." Any user who opens their browser's developer tools can now see the key and use it to forge payment verifications. Payment API keys, service role keys, and any credential with write access belong exclusively in backend code — in Supabase edge function environment variables, never in the frontend.
fee_structures table and ignore any amount sent from the client. This is the equivalent of not letting a client self-certify their own tax liability without verification. The rule is the same: critical values must be independently verified by the authoritative source.How Claude Code Helps in This Role
Write a Supabase query:
"Write a Supabase TypeScript query to fetch all fee records for students in the logged-in branch admin's branch, where the status is overdue and the due_date is more than 30 days ago. Include the student's full name, class name, fee type, and amount. Sort by due_date ascending."
Write an edge function:
"Write a Supabase edge function that: receives a fee_record_id and a Razorpay payment_id and signature, verifies the caller is the parent linked to that fee record, verifies the Razorpay signature, and updates the fee record status to paid with the payment details."
Design a business rule:
"I need to prevent a teacher from marking attendance for the same class twice on the same day. Where should this check live — in a database unique constraint, a database trigger, or an edge function? Show me how to implement it."
Review backend code for security:
"Review this edge function for security issues. Does it validate the caller's identity? Does it verify that the parent can only pay fees for their own child? Are there any cases where a user could manipulate the outcome?"
What to watch for in Claude's backend output:
- Does it validate the caller is authenticated?
- Does it validate all inputs?
- Does it handle errors explicitly (not just the happy path)?
- Are any secrets or keys visible in the code?
- Does it use the correct Supabase client (server-side client for edge functions, not the browser client)?
How to Switch Into This Role
Before writing any backend code, say:
"I am not building what users see. I am building the rules and logic that decide what users are allowed to do and what data they get back. Security matters here. Correctness matters here. An error here can lose money, expose private data, or corrupt the database."
Then for each backend feature, define:
- Who is allowed to call this? (Authentication check)
- What input am I receiving, and what is valid? (Validation)
- What business rule does this enforce?
- What should happen when something goes wrong?
- What should I log so I can debug problems later?
Exercise
Take the Udyogaseva project. Open the Supabase dashboard for the project (ask Subhash for access, or open the edge functions in the codebase at S:\Client Projects\012601 Udyogaseva\supabase\functions\).
Pick one edge function. Read it with these questions in mind:
You do not need to understand every line of syntax. Look for the structure: authentication → validation → business logic → external call → response. That structure is in every well-built edge function. Once you can see it, you can build it.