Project · Backend Development
Project: the data and security layer of a food-delivery app
The brief
Hyderabad Eats connects customers with restaurants across the city. Write the SQL behind its screens (joins, revenue with GROUP BY and HAVING, a win-back list, best sellers with a window function, an order placed in a transaction) and the security code around it: injection-safe queries, password hashing and order permissions.
Why it matters
Food-delivery, quick-commerce and ride apps live on these queries, and their worst incidents come from the same three mistakes: SQL built from user text, weak password storage, and one customer reading another customer's orders by changing an id in the URL. Backend interviews at product companies cover all of it.
Skills you practise
- JOIN and LEFT JOIN
- GROUP BY, HAVING and COUNT(DISTINCT)
- window functions (ROW_NUMBER)
- transactions
- parameterised queries and allow-lists
- PBKDF2 password hashing with Web Crypto
- authorization (object-level access checks)
What you will have at the end
Five SQL files for the app's screens and security.js (safe search, password hashing, permissions), all tested.
How it is marked (rubric, 100 points)
| Correct resultsEvery check passes. | 40 |
|---|---|
| Secure by designOnly placeholders for user values, allow-lists for sorting, salted slow hashes, deny-by-default permissions. | 30 |
| Good SQLClear joins with aliases, COUNT(DISTINCT) where needed, CTEs for readability, a transaction for multi-row writes. | 20 |
| Can explainYou can explain SQL injection, why salts matter, and what IDOR (insecure direct object reference) is. | 10 |
0/8 steps done
Step 1 of 8
Orders of one day, with names
01-orders-on-date.sql returns order id, customer name, restaurant name and status for every order placed on 2026-10-02, in time order.
The orders table only stores ids. A JOIN brings in the matching row from another table through the foreign key: orders.customer_id = customers.id. Short aliases (o, c, r) keep the query readable. ordered_at is text like "2026-10-02 08:15", so date(o.ordered_at) gives just the day to compare.
Run shows what your code prints. Check runs the step's tests. Ctrl+Enter checks too.