idname
1Anjali
2Rahul
iddept
1CSE
2ECE
student_idcourse_id
15
ancestordepth
A2
Expert Talk Β· Dept. of CSE, LBS College of Engineering, Kasaragod

From Idea to App
Build with AI

Databases, AI tools, and how real software gets built.

Vipindas K Β· Software Engineer, Hexeam Software Solutions

Classroom vs real project

You know the theory. Now the real questions.

In the classroomIn a real project
Define primary key and foreign keyWhat happens when a parent row is deleted?
Normalise this table to 3NFWhen is it worth breaking the rule, and why?
What is an index?Which column, and what does it cost?
Write the 4 ACID propertiesTwo users click Register at the same moment. Now what?
Draw a one-to-many ER diagramOne notifications table for 3 kinds of users?
SQL is the database languageSQL, MongoDB, Firebase or Redis: which, for my project?
Modern software workflow

How real software gets built

πŸ’‘

Idea

Who needs it, and why

πŸ—ƒοΈ

Design

The data first, then screens

🌿

Build

One Git branch per change

πŸ”

Review

Pull request and automatic tests

πŸš€

Deploy

Staging, then production

πŸ“ˆ

Monitor

Logs, feedback, improve

Why today goes deep on the database: code is easy to change. A live database full of real users' data isn't, so a bad design there costs the most.
And AI? It helps at every step, but the steps stay. Our live demo follows the same loop: spec, plan, build, check, deploy.
The next 75 minutes

Agenda

πŸ— Real projects along the way: attendance, online shop, ticket booking, wallet, canteen. Then: team habits, skills and opportunities.

01

πŸ—ΊοΈ DB landscape

SQL, MongoDB, Firebase, Redis. Which one when?

02

πŸ”‘ MySQL basics

Keys, indexes, normal forms.

03

πŸ”— Relations

One-to-many, many-to-many, polymorphic.

04

🀝 Joins

Row by row, so you never forget.

05

⚑ Same-time problems

Transactions, locks, two users, one ID.

06

🌳 Trees

Closure table: insert and delete.

07

πŸ” Login

How it really works, in tables.

08

πŸ€– AI + live reveal

Vibe coding, AI tools, which model. Then open the tool.

Live demo Β· kickoff

Let's give the AI a job: JoinLab

~/live-demo Β· claude
# the full spec is in CLAUDE.md $ claude --permission-mode plan > Read CLAUDE.md and build JoinLab exactly as specified. Plan first: the milestones only. After I approve, do them in order, deploying with bash deploy.sh at each milestone. Keep it small. Don't ask me questions unless something blocks you.
Theater: two tables stand apart, come together, and the join happens in front of you
Builder: make tables with a GUI, and see the SQL
Lab + Missions: real SQL, graded practice
Login (bonus): keep your own data, if time allows
Status: % and stuck warnings in the bottom panel ⬇
The main four

Four databases to know first

πŸ“Š

SQL

Tables with strict columns and relations. The default for most apps.

MySQLPostgreSQLSQLite
πŸ“„

MongoDB

JSON-like documents. Flexible shape, easy to spread across servers.

Document DB
πŸ”₯

Firebase

Google's cloud backend. Changes reach every phone in real time.

FirestoreRealtime DB
⚑

Redis

Lives in memory, extremely fast. Cache, OTP, sessions, queues.

Key-value
Same data, four shapes

One student, four ways to store

πŸ§‘β€πŸŽ“ Anjali Β· CSE Β· php, sql

πŸ“Š SQL: rows in tables

students departments id | name | dept_id id | name 1 | Anjali | 1 β†’ 1 | CSE

πŸ“„ MongoDB: one document

{ "_id": 1, "name": "Anjali", "dept": { "name": "CSE" }, "skills": ["php", "sql"] }

πŸ”₯ Firebase: synced to every device

students/1 β†’ { name: "Anjali", dept: "CSE" } change it β†’ all open phones update instantly

⚑ Redis: key β†’ value, with expiry

SET otp:9876543210 "482913" EX 300 gone by itself after 5 minutes
Inside the SQL family

MySQL Β· PostgreSQL Β· SQLite

🐬 MySQL

App
SQL
Server

A separate server process. Simple and popular, the default for most websites.

🐘 PostgreSQL

App
SQL
Server

Also a server, with more power: JSONB, full-text search, maps, advanced types.

πŸͺΆ SQLite

App + data.sqliteno server, one file

A library inside your app. Zero setup. Used in phones, browsers and small tools.

Compare

Which SQL database?

MySQLPostgreSQLSQLite
Runs asServerServerFile inside the app
SetupEasyEasy to mediumNone
Many writers at onceYesYesOne writer at a time
StrengthSimple, widely hostedRich features, strict rulesTiny, portable, offline
Pick it forWebsites, college appsComplex data, analytics, mapsMobile apps, prototypes, small tools

πŸ’‘ All three speak SQL. Learn one well and the others come easily.

Relational vs non-relational

One order, two designs

πŸ“Š Relational: split, then linked

orders
iduser
1Anjali
2Rahul
order_items
orderproduct
17
27
products
idname
7PenGel Pen
Rename the product: change 1 row. Every order sees it. βœ…
Read an order: needs a JOIN of 3 tables.

πŸ“„ Non-relational: all in one

orders { id: 1, user: "Anjali", items: [{ name: "Pen" }] } { id: 2, user: "Rahul", items: [{ name: "Pen" }] }
Rename the product: update every document. ⚠️
Read an order: one document, no join. βœ…

Relational protects correct data. Non-relational gives flexibility and easy scale.

Use cases

What would you pick?

ProjectPickWhy
College ERP, marks, feesMySQL / PostgreSQLStrong relations, correct data
Online paymentsMySQL / PostgreSQLTransactions keep money correct
Product catalogue, each item with different fieldsMongoDBFlexible document shape
Live chat or live score appFirebaseReal-time sync, little backend code
OTP, cache, login sessionsRedis (alongside SQL)Fast, expires by itself
Offline notes app on a phoneSQLiteA file on the device

Rule: start with one SQL database. Add others only for a real need.

Keys

The keys that hold data together

students
idreg_nonamedept_id
1KSD22CS001Anjali1
2KSD22CS002Rahul1
3KSD22EC001Fathima2
departments
idname
1CSE
2ECE
enrollments
student_idcourse_id
15
17
Primary key: identifies each row. Unique, never NULL, one per table.
Unique key: no duplicates allowed, but not the row's main identity.
Foreign key: points to a primary key in another table. This is the link.
Composite key: two columns together are unique. Student 1 can't take course 5 twice.
Candidate key: any column that could be the primary key, like id or reg_no. You choose one.
Foreign keys protect data

The database says no

INSERT INTO students (name, dept_id) VALUES ('Arun', 99); βœ— ERROR: foreign key constraint fails. Department 99 doesn't exist.
πŸ›‘οΈ departments
idname
1CSE
2ECE

And when you delete the CSE department, what happens to its students? You decide:

RESTRICT

Refuse the delete while students exist. The safe default.

CASCADE

Delete the students too. Good for order items; dangerous elsewhere.

AnjaliRahul

SET NULL

Keep the students, with dept_id = NULL. They're unassigned.

Indexing

Find one student among 10 lakh

🐒 No index: full table scan

email
rahul@…
fathima@…
arjun@…
… every row …
anjali@… βœ“ found last

Rows checked: 0

πŸš€ With an index: a sorted tree (B-tree)

a–z a–mn–z an…f…n…r…

Steps taken: 0

Worst case: every row gets checked.
Just a few steps, like the index at the back of a textbook.
CREATE INDEX idx_students_email ON students (email); -- one line, one column
Index trade-offs

Why not index every column?

βœ… Index it when

  • Used in WHERE
  • Used in JOIN (foreign keys)
  • Used in ORDER BY
  • Many different values

❌ Disadvantages

  • INSERT and UPDATE get slower
  • Uses extra disk space
  • Too many confuse the design

🚫 Skip it when

  • Very small tables
  • Few values, like yes / no
  • Column rarely searched
-- Composite: order matters (leftmost first) CREATE INDEX idx ON students (dept_id, name); WHERE dept_id = 1 AND name = 'Anjali' βœ“ used WHERE name = 'Anjali' βœ— not used
-- Is my query using the index? EXPLAIN SELECT * FROM students WHERE email = 'anjali@…'; -- type: ALL = full scan (slow) -- type: ref = index used (fast)
πŸ— Real project Β· college attendance

One small feature, 12 lakh rows a year

πŸ“ˆ Rows in a year: 0
attendance
student_iddateperiodstatus
12026-11-051P
22026-11-051P
12026-11-052P
32026-11-052A
12026-11-061A
22026-11-061P
The maths: 1,000 students Γ— 6 periods Γ— 200 days.
The report: Anjali's attendance this semester. With no index, MySQL reads every row.
SELECT SUM(status='P') * 100 / COUNT(*) FROM attendance WHERE student_id = 1 AND date >= '2026-06-01';
The fix: a composite index. Now MySQL goes straight to Anjali's rows.
CREATE INDEX idx_student_date ON attendance (student_id, date);
Teacher taps Save twice? UNIQUE (student_id, date, period) refuses the copy.
Normal forms Β· 1NF

1NF: one value in each cell

❌ students
idnamephones
1Anjali9876…, 9447…
2Rahul9995…
β†’
βœ… students
idname
1Anjali
2Rahul
βœ… phones
student_idphone
19876…
19447…
29995…
Problem: try finding β€œwho has 9447…”, or removing one number. You'd have to cut text apart.
Fix: a new table, with one row per phone.
Result: each cell holds one value, and each student can have any number of phones.
Normal forms Β· 2NF

2NF: depend on the whole key

❌ enrollments, key = (student_id, course_id)
student_idcourse_idstudent_namegrade
15AnjaliA
17AnjaliB
25RahulA
βœ… enrollments
student_idcourse_idgrade
15A
17B
25A
βœ… students
idname
1Anjali
2Rahul
Problem: the name depends only on student_id, part of the key. It repeats on every row.
Fix: move it to the students table. The grade needs both columns, so it stays.
Result: a name change touches one row, not hundreds.
One-to-one

Has one Β· belongs to

users
idname
1Anjali
2Rahul
profiles
iduser_id FK + UNIQUEphoto
101a.jpg
112r.jpg
User has one profile. Read it from the users side.
Profile belongs to a user. Same link, read from the other side.
Where's the foreign key? Always on the β€œbelongs to” table.
UNIQUE stops a second profile for the same user.
One-to-many Β· many-to-one

One line, two directions

departments (one)
idname
1CSE
2ECE
students (many)
idnamedept_id FK
1Anjali1
2Rahul1
3Fathima2
One-to-many: department has many students.
Many-to-one: each student belongs to one department.

Rule: the foreign key goes on the many side. You can't fit many ids in one cell (1NF!).

Many-to-many

A third table: the pivot

students
idname
1Anjali
2Rahul
enrollments (pivot)
student_idcourse_id
15
17
25
courses
idtitle
5DBMS
7OS
A student takes many courses (DBMS and OS).
A course has many students (Anjali and Rahul take DBMS).
Bonus: the pivot can hold extra data, like grade or joined date.
Polymorphic Β· morph one / morph many

One table that points to many tables

students
idname
1Anjali
teachers
idname
1Dr. Nair
admins
idname
4Office
notifications
idowner_typeowner_idmessage
1student1Fee due
2teacher1Marks pending
3admin4Server backup OK
Two columns do the work: which table (type) + which row (id). Student 1 and teacher 1 stay different.
Morph many: one student has many notifications. Morph one: one owner has one row, like a profile photo.
SELECT * FROM notifications WHERE owner_type = 'teacher' AND owner_id = 1;
⏩ Polymorphic many-to-many

Morph to many Β· morphed by many

posts
idtitle
1SQL tips
videos
idtitle
1Joins 101
taggables (pivot)
tag_iditem_typeitem_id
7post1
8post1
7video1
tags
idname
7database
8beginner
Morph to many: a post has many tags.
The same pivot serves videos too. No second pivot table needed.
Morphed by many: the tag β€œdatabase” is used by posts and videos.
⚠️ Trade-off: owner_id can't be a real foreign key, so your code must keep it correct.
Joins Β· row by row

INNER JOIN: only matches survive

SELECT s.name, d.name FROM students s INNER JOIN departments d ON s.dept_id = d.id;
students
namedept_id
Anjali1
Rahul1
Fathima2
Arjun3
Neha2
VishnuNULL
departments
idname
1CSE
2ECE
3Mech
4Civil
result: 5 rows
studentdepartment
AnjaliCSE
RahulCSE
FathimaECE
ArjunMech
NehaECE
Vishnu: dept_id is NULL, so no partner. Dropped from the result.
Civil: no students point to it. It doesn't appear either.
Joins Β· keep the unmatched

LEFT Β· RIGHT Β· FULL

LEFT JOIN: 6 rows

All students. Vishnu stays, with department NULL.

VishnuNULL

RIGHT JOIN: 6 rows

All departments. Civil stays, with student NULL.

NULLCivil

FULL JOIN: 7 rows

Everyone. MySQL has no FULL JOIN: combine LEFT and RIGHT with UNION.

-- A favourite interview question: students with no department SELECT s.name FROM students s LEFT JOIN departments d ON s.dept_id = d.id WHERE d.id IS NULL;
⏩ Two things you'll need soon

GROUP BY and the N+1 mistake

πŸ“Š GROUP BY + HAVING

SELECT d.name, COUNT(s.id) AS total FROM departments d LEFT JOIN students s ON s.dept_id = d.id GROUP BY d.id, d.name HAVING total >= 2;

WHERE filters rows before grouping. HAVING filters groups after.

🐌 The N+1 mistake

-- ❌ 1 query, then 1 more per student SELECT * FROM students; SELECT * FROM departments WHERE id = ?; -- … 1000 students = 1001 queries -- βœ… one JOIN gets it all at once

Works fast on your laptop, crawls with real data.

πŸ— Real project Β· online shop

The price went up. Did the old bill change?

users
idname
1Anjali
orders
iduser_id
5011
order_items
order_idproduct_idqtyprice
50171β‚Ή999
products
idnameprice
7Earphonesβ‚Ή999
SELECT p.name, oi.qty * p.priceoi.price AS total FROM order_items oi JOIN products p ON p.id = oi.product_id WHERE oi.order_id = 501;
🧾 Bill #501: β‚Ή999
The problem: Anjali paid β‚Ή999 in January. That old bill now says β‚Ή1,299.
The fix: copy the price into order_items at purchase.
Not a normalisation mistake: the price paid and today's price are two different facts. Do the same for the delivery address and tax.
Keep your data safe

SQL injection and backups

// ❌ the input becomes part of the SQL "SELECT * FROM users WHERE email = '" + email + "'" email = ' OR 1=1 -- β†’ returns every user!
// βœ… prepared statement: input is only data "SELECT * FROM users WHERE email = ?" + [email]
  • Back up every day, automatically
  • Test a restore: an untested backup is only a hope
  • Least privilege: the app's DB user can't drop tables
Procedural language

Code that lives inside the database

CREATE PROCEDURE enroll(IN s INT, IN c INT) BEGIN IF (SELECT COUNT(*) FROM enrollments WHERE course_id = c) >= 60 THEN SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'Course is full'; END IF; INSERT INTO enrollments VALUES (s, c); END; CALL enroll(1, 5); -- run it from any app
Stored procedure: a named program. Run it with CALL.
Function: returns a value, usable inside a SELECT.
Trigger: runs by itself on INSERT, UPDATE or DELETE. Good for audit logs.
Use sparingly: harder to test and review than normal app code.
Transaction

All steps succeed, or none do

Anjali

β‚Ή5000
➜

Rahul

β‚Ή2000
START TRANSACTION; UPDATE accounts SET bal = bal - 1000 WHERE name = 'Anjali'; ⚑ power cut! β†’ ROLLBACK -- try again UPDATE accounts SET bal = bal + 1000 WHERE name = 'Rahul'; COMMIT; βœ“ saved for good
Crash halfway: the debit is undone. No money vanishes.
Atomic: all or nothing
Consistent: rules always hold
Isolated: others don't see half-done work
Durable: after COMMIT, it survives a crash
Locks

One biryani left, two students

πŸ› Biryani Β· stock = 1 πŸ”“πŸ”’πŸ”“
πŸ™‹ User A
πŸ™‹ User B
step 1
SELECT stock FROM menu_items WHERE id=1 FOR UPDATE πŸ”’ got it
step 2
Same query: ⏳ waiting…
step 3
UPDATE menu_items SET stock = 0 WHERE id=1
step 4
COMMIT πŸ”“ released, ordered!
step 5
Reads stock = 0: β€œSold out”
Shared lock: many can read, nobody writes.
Exclusive lock: one writer, others wait.
Row lock: only that row waits (InnoDB, needs an index).
Table lock: the whole table waits. Avoid it.
Deadlock: two users wait for each other, and MySQL cancels one. Always lock in the same order.
A real bug Β· race condition

Two users register at the same moment

πŸ™‹ Anjali clicks Register
πŸ™‹ Rahul clicks Register
10:00:00.01
SELECT MAX(reg_no) β†’ 100
SELECT MAX(reg_no) β†’ 100
10:00:00.02
100 + 1 = 101
100 + 1 = 101
10:00:00.03
INSERT reg_no 101 βœ“
INSERT reg_no 101 πŸ’₯
πŸ—„οΈ students Β· reg_no: 100, 101, 101 πŸ’₯
Both read before either one has saved.
Same maths, so the same number.
No UNIQUE: two students share one ID. With UNIQUE: Rahul gets an error.
On your laptop it never happens. On results day, it happens every minute.
The fix

Same moment, two different IDs

πŸ”’ counters.last_no = 100
πŸ™‹ Anjali
πŸ™‹ Rahul
Locks counter πŸ”’ reads 100
Waits for the lock ⏳
Saves 101, COMMIT πŸ”“
Locks counter πŸ”’ reads 101
Saves 102, COMMIT πŸ”“
START TRANSACTION; SELECT last_no FROM counters WHERE name='reg' FOR UPDATE; UPDATE counters SET last_no = last_no + 1 WHERE name='reg'; INSERT INTO students (reg_no, name) VALUES (…); COMMIT;
Plain ID: AUTO_INCREMENT. The database hands out unique numbers, with no code. Gaps can appear, and that's fine.
Formatted no. (KSD22CS101): counter row + lock, as here.
Always add UNIQUE as the final safety net.
πŸ— Real project Β· ticket booking

Last seat, one winner

πŸ™‹ AnjaliπŸ’Ί A5πŸ™‹ Rahul
bookings Β· UNIQUE (show_id, seat_no)
show_idseat_nouser
7A5Anjali
βœ— ERROR 1062: Duplicate entry '7-A5' Rahul's app says: β€œSorry, just sold.”
Same second: both tap A5, so two INSERTs arrive.
Anjali's lands. The seat is booked.
Rahul's is refused. UNIQUE is the final safety, even if your code has a bug.
While paying: hold the seat for 5 minutes. 1 row changed means yours; 0 means taken.
UPDATE seats SET held_by = 1, held_until = NOW() + INTERVAL 5 MINUTE WHERE id = 55 AND (held_until IS NULL OR held_until < NOW());
Why not a lock? Paying takes minutes. Locks should last milliseconds.
πŸ— Real project Β· UPI-style wallet

Double tap, charged once

πŸ“± Pay β‚Ή500πŸ’° Balance: β‚Ή5,000
ledger Β· UNIQUE (idem_key)
iduser_idamountidem_key
11+5000topup-1
21βˆ’500pay-9f2c
βœ— ERROR 1062: Duplicate entry 'pay-9f2c' The app shows the first result. No second charge.
Tap Pay: the app makes one key for this payment and sends it along.
Slow network, second tap or auto-retry: same key, so UNIQUE refuses it. The balance stays β‚Ή4,500.
A ledger, not only a balance: every rupee movement is a row, so you can always explain the balance.
SELECT SUM(amount) FROM ledger WHERE user_id = 1;
For speed: many apps also keep a balance column, updated in the same transaction. The ledger stays the truth.
Beyond the textbook Β· trees

Storing a tree in flat tables

🌳 Binary

Max 2 children: left and right.

πŸ”² Matrix

Fixed width, like 3 children, then the next level fills.

🌿 Unilevel

Unlimited children. Also comment threads, folders.

Simple design: a parent_id column. Finding a direct parent or child is easy.
The problem: β€œeveryone under A” needs one query per level, or recursion, and gets slower as the tree grows.
Closure table Β· binary tree

Store every path, not just the parent

ABCDELRLR
tree_paths Β· 11 rows
ancestordescendantdepth
AA0
BB0
AB1
CC0
AC1
DD0
BD1
AD2
EE0
BE1
AE2
Each row says: this node is above that node, by N steps. Every node also has a self row, depth 0.
B's team: WHERE ancestor='B' AND depth>0
D's upline: WHERE descendant='D' AND depth>0
Cost: more rows and more writes, for very fast reads. No recursion. Used for referrals, org charts, product categories and comment threads.
Closure table Β· insert

Insert a node: rows arrive

ABCDEFLLRLR
tree_paths rows: 11
ancestordescendantdepth
AA0
BB0
AB1
CC0
AC1
DD0
BD1
AD2
EE0
BE1
AE2
FF0
CF1
AF2
New member F joins under C, on the left.
Self row: F to F, depth 0.
Copy C's rows, depth + 1: C→C 0 becomes C→F 1. A→C 1 becomes A→F 2.
INSERT INTO tree_paths (ancestor, descendant, depth) SELECT ancestor, 'F', depth + 1 FROM tree_paths WHERE descendant = 'C' UNION ALL SELECT 'F', 'F', 0;
Closure table Β· delete

Delete a node: rows leave

ACBDELLRFLR
tree_paths rows: 14
ancestordescendantdepth
AA0
BB0
AB1
CC0
AC1
DD0
BD1
AD2
EE0
BE1
AE2
FF0
CF1
AF2
Delete leaf F: its 3 rows go.
DELETE FROM tree_paths WHERE descendant = 'F';
Delete B's whole team: B, D and E go, with 8 rows.
DELETE FROM tree_paths WHERE descendant IN ( SELECT descendant FROM ( SELECT descendant FROM tree_paths WHERE ancestor = 'B' ) t);
In real apps: usually soft delete, or move the children up. Removing one person shouldn't silently remove their team.
Login

Authentication vs Authorization

πŸͺͺ

Authentication

β€œWho are you?”

College gate: security checks your ID card.

πŸšͺ

Authorization

β€œWhat can you do?”

Inside: only lab staff can open the server room.

⏩ Login types

Many logins, all stored in tables

πŸ”‘

Password

users.pass_hash. Never plain text.

πŸ“²

OTP

A short code with expiry. Often in Redis.

βœ‰οΈ

Magic link

A one-time token sent by email.

🌐

Google login

users.google_id. No password stored.

πŸ‘†

Passkey

Fingerprint on the device. Server keeps a public key.

πŸ›‘οΈ

2FA

Password + a code from an authenticator app.

🏒

SSO

One login for many apps.

🎟️

API token

For mobile apps and other programs.

How a password login works

Sessions and cookies, in tables

πŸ’»Browseryou
email + passwordπŸͺ session idπŸͺ + next page
βš™οΈServeryour code
find userhash βœ“
πŸ—„οΈDatabaseusers, sessions
1. The form sends email + password over HTTPS
2. Compare with users.pass_hash (bcrypt), never plain text
3. Save a row in sessions, and send its id as a cookie (HttpOnly)
4. Every next request carries the cookie: β€œstill me”
πŸ— Real project Β· canteen pre-order

From idea to tables

β€œStudents pre-order food from the canteen, pay online, and collect their order with a token.”

πŸ‘€ users
id
name
phone
πŸ’³ payments
id
order_id
amount
idem_key
πŸ“‹ orders
id
user_id
token_no
status
pickup_at
🧾 order_items
order_id
item_id
qty
price
πŸ› menu_items
id
name
price
stock
Only 50 biryani? Transaction, and lock the stock row.
Token number? Never MAX + 1. Use a counter row with a lock.
Pay tapped twice? UNIQUE idempotency key.
OTP login? Start in SQL. Add Redis only when you need it.
Starting your own project

Decide these before you code

QuestionUsual answer
What's the data like?Linked data β†’ MySQL / PostgreSQL
Need live updates, no backend?Firebase
Which language do I know?PHP, JS, Python: the one you know is best
Framework?Laravel, Express, Django: login and DB tools built in
Where will it run?A small VPS, or a free tier to start

πŸ€– Ask AI to think with you

I'm building a canteen pre-order app for 500 students. I know PHP. Suggest a database, framework and tables. Explain why, list the trade-offs, and don't write code yet.

AI proposes. You decide.

Industry best practices

Habits every team expects

🌿 Git and review

Every change on a branch, reviewed by someone before it merges.

πŸ§ͺ Automatic tests

Checks run on every change, so old features don't silently break.

πŸ—ƒοΈ Migrations

Database changes are versioned files, never manual edits on the server.

πŸ”’ Secrets

Passwords and keys live in .env, never in Git.

🧭 Staging first

Try it on a copy. Never test on live data.

πŸ“ˆ Logs and backups

Know when it breaks, and test that the backup really restores.

πŸ— Real-world project experience

What real projects teach you

πŸ”„ Requirements change

Even after you've built it. Keep your design easy to change.

πŸ“ˆ Data grows

Fast with 100 rows can crawl with 10 lakh.

πŸ“– You mostly read code

The job is understanding and changing code that already exists.

πŸ™‹ Real users surprise you

Double taps, slow networks, input you never imagined.

🎀 From my own work: a real story.
πŸ€– Building with AI Β· vibe coding

Vibe coding: fast, until it isn't

πŸ’¬ Describe
prompt
πŸ€– AI writes
code
▢️ Run it
result
πŸ—£οΈ β€œFix this”

βœ… Great for

Prototypes, demos, personal tools, and learning a new idea.

⚠️ Review every line

Login, payments, and anything holding real users' data.

AI often writes what we warned about today: MAX + 1 IDs, no UNIQUE, no index, input glued into SQL. Now you can catch them.
You own what you ship. JoinLab isn't pure vibes: it has a spec, a plan and automatic checks.
πŸ€– Building with AI Β· major tools

Four types of AI tool

TypeExamplesUse it forWatch out
πŸ’¬ Chat assistantClaude, ChatGPT, GeminiThink, plan, explain an errorOnly knows what you paste in
✏️ AI code editorCursor, GitHub Copilot, WindsurfAutocomplete and edits as you codeEasy to accept without reading
πŸ–₯️ Terminal agentClaude Code, Codex CLI, Gemini CLIPlan, change many files, run testsNeeds a clear spec and permission limits
⚑ App builderLovable, Bolt, v0, ReplitA working prototype from a promptCheck its database and login

Today's JoinLab is built by a terminal agent. Start with one chat tool and one coding tool. Names change; the four types don't.

πŸ€– Building with AI Β· choosing a model

Pick the model by the job

🎯 What's the job?

🧠 Most capable

Claude Opus tier. Slowest, highest cost. For decisions that are expensive to get wrong.

Plan the database

βš–οΈ Balanced

Claude Sonnet tier. Good speed and quality. Your default for coding.

Build the screens

⚑ Small and fast

Claude Haiku tier. Cheapest, fastest. For simple, repeated work.

Check the result
That's today's build: Opus plans, Sonnet builds, Haiku checks. OpenAI and Google offer similar tiers.
Ask: How hard is it? How many calls, at what cost? How fast must it reply? Is the data private? If it is, read the data terms or run an open model locally.
Test on your real task, starting cheap. Move up only if the results aren't good enough. Names and prices change every few months.
Live Β· built by an AI agent during this class

Meet JoinLab πŸš€

Watch joins happen, build tables with a GUI, write real SQL.

  • Theater: students LEFT JOIN departments
  • Lab: type your own query
  • Missions: can you finish all of them?
For aspiring software engineers

Skills and opportunities

🧱 What companies look for

  • DBMS, OOP, data structures
  • One language and framework, properly
  • SQL and Git
  • Reading and debugging code
  • Clear communication

πŸšͺ Where you can start

  • Backend, frontend, full stack, mobile
  • QA, DevOps, data
  • Product, service, startup
  • Internships, freelance, open source

🎯 Your next 6 months

  • Build one real project, end to end
  • Deploy it, and put the link on your resume
  • Keep the code on GitHub
  • Try one internship or open source fix
Your edge: AI makes typing code cheaper. Understanding the problem and the data gets more valuable.
Recap

From idea to app: take these home

  • Start with one SQL database; add others on real need
  • Keys link data; indexes make it fast, at a cost
  • Normalise so each fact lives in one place
  • Foreign key goes on the many side; many-to-many needs a pivot
  • Transactions and locks keep same-time users correct
  • Never calculate IDs yourself. Let the database do it
  • UNIQUE is your final safety; copy facts that must not change, like the price paid
  • Vibe code prototypes, but review login, money and data; pick the model by the job

🎯 This week

  • Finish all JoinLab missions
  • Design tables for your project
  • Practise joins until they feel easy
  • Put one project on GitHub
Thank you

Questions? πŸ™‹

Exams test what you remember. Real apps test what you understood.

Vipindas K Β· Software Engineer, Hexeam Software Solutions

vipindas.k@hexeam.in

Thanks to Reema K V (Faculty Coordinator), Sumayya Zakiya (Student Coordinator) and the Department of CSE, LBS College of Engineering, Kasaragod

All slidesO / Esc to close

Keyboard shortcuts

β†’ Space PgDn
Next step / slide (clicker works)
← PgUp
Previous
12 + Enter
Jump to slide 12 (or G)
F
Full screen
O
Overview of all slides
P / H
Pen / highlighter (1–5 colours, [ ] size)
L / S
Laser pointer / spotlight (wheel or +/- size)
E / Z / C
Eraser / undo / clear slide
W
Whiteboard (blank board)
B or .
Black screen
T / Shift+T
Timer with 75‑min plan / reset timer
D
Hide or show the live build status
Esc
Stop tool, close panels
Phone
Swipe or tap edges · ✎ button for tools