Expert: design, speed and engines · Procedures, triggers, SQL engines and NoSQL · topic 57 of 62 · 35 min
Choosing a database, and keeping it safe
Explanation
A decision guide
Most apps start with one relational database, such as PostgreSQL or MySQL, and that is the right default: it handles transactions, joins, reports and a lot of traffic. Add another kind of database only when a need clearly calls for it.
| Need | Good choice | Why |
|---|---|---|
| Orders, payments, users, anything with rules and money | Relational (PostgreSQL, MySQL, SQL Server) | ACID transactions, constraints, joins |
| Cache, sessions, rate limits, leaderboards | Redis (or Valkey) | In-memory, sub-millisecond, expiry built in |
| Records whose fields vary a lot | MongoDB, or a JSONB column in PostgreSQL | Flexible documents |
| Full-text search with typos, filters and ranking | Elasticsearch or OpenSearch | Inverted indexes built for search |
| Metrics and sensor readings over time | Time-series (TimescaleDB, InfluxDB) | Fast inserts and time-window queries |
| Big analytical reports over years of data | A warehouse (BigQuery, Snowflake, Redshift, ClickHouse) | Column storage built for scans and aggregates |
Using several databases, each for what it does best, is called polyglot persistence. It is powerful but every extra database is something to run, monitor, back up and keep in sync. A common pattern is: the relational database is the source of truth, and the others (cache, search index) are copies fed from it.
Least privilege, GRANT and REVOKE
Least privilege means each user or app gets only the rights it needs. The reporting tool reads; it never deletes. The web app writes orders; it never drops tables. If one password leaks, the damage stays small. In SQL you give rights with GRANT and take them away with REVOKE (DCL, from module 1).
-- PostgreSQL (MySQL and SQL Server are similar)
CREATE ROLE report_reader LOGIN; -- password set separately by the admin
GRANT CONNECT ON DATABASE shop TO report_reader;
GRANT USAGE ON SCHEMA public TO report_reader;
GRANT SELECT ON orders, order_items, products TO report_reader;
REVOKE INSERT, UPDATE, DELETE ON products FROM web_app;SQL injection
SQL injection happens when an app builds a query by gluing user input into the SQL text. The input can then change the meaning of the query. Suppose a login form builds:
-- The app glues the typed name into the SQL text:
-- "SELECT id, username, role FROM users WHERE username = '" + name + "'"
-- An attacker types: ' OR '1'='1
SELECT id, username, role FROM users WHERE username = '' OR '1'='1';
-- returns EVERY user, including adminThe fix is not to "clean" the input by hand. Use parameterised queries (also called prepared statements): the SQL text has placeholders, and the values are sent separately, so they can never become SQL.
import sqlite3
con = sqlite3.connect('shop.db')
name = "' OR '1'='1" # whatever the user typed
# WRONG: never build SQL with + or f-strings
# con.execute("SELECT id FROM users WHERE username = '" + name + "'")
# RIGHT: a ? placeholder, value passed separately
rows = con.execute("SELECT id, username FROM users WHERE username = ?", (name,)).fetchall()
print(rows)
# Output: [] (no user is literally called ' OR '1'='1)// Node.js with the pg library (PostgreSQL uses $1, $2...)
const { rows } = await client.query(
'SELECT id, username FROM users WHERE username = $1',
[name]
);Backups and restore drills
A backup you have never restored is a hope, not a backup. Take regular backups (pg_dump, mysqldump, SQLite's .backup command or VACUUM INTO, or the managed service's snapshots), keep a copy in another place, and practise restoring to a test server on a schedule. Two numbers guide the plan: RPO, how much data you can afford to lose (for example 5 minutes), and RTO, how long you can be down (for example 1 hour).
Managed databases
A managed database is one a cloud provider runs for you: it handles installs, patches, backups, replicas and failover, and you pay for it. Examples: Amazon RDS and Aurora, Google Cloud SQL, Azure SQL Database, and newer serverless PostgreSQL services such as Neon and Supabase (which adds auth and APIs on top). You still own the schema, the queries, the users and the security settings.
Common mistakes
- Adding MongoDB, Redis and Elasticsearch on day one. Start with one relational database and add others when a need is proven.
- Letting the app connect as the database owner or root. Create a separate user with only the rights the app needs.
- Gluing input into SQL with + or f-strings, even "just for an admin page". Use placeholders everywhere.
- Never testing restores. Schedule a restore drill and time it.
- Leaving a database open to the whole internet. Allow only your app servers' network.
Need help?
Stuck on a word or an idea? Search this course, or every course, and jump straight to the explanation or a worked question.
Try:
Watch the lesson
Choosing a database, and keeping it safe · 1/8
How do you pick a database, and how do you keep it safe? Start with a simple rule.
Prefer a video by a teacher? Find free videos on “how to choose a database sql injection parameterized queries least privilege” on YouTube ↗
In real life: A typical stack for a food-delivery app
A food-delivery platform could keep customers, restaurants, orders and payments in PostgreSQL; cache menus and store rider locations in Redis; index restaurants and dishes in OpenSearch so "paneer tikka near me" works with typos; and copy order history into a warehouse for the business team's reports. Each part has its own database user with only the rights it needs, all queries use parameters, and nightly backups are restored to a test server every month. This is an illustrative design, not any specific company's setup.
Practice (0/4 done)
Learn the attack so you can defend against it. A careless app builds: SELECT id, username, role FROM users WHERE username = '<typed text>'. An attacker types ' OR '1'='1 as the username. Write the exact query the app ends up running (paste the typed text in place of <typed text>) and run it to see that it returns id, username and role of every user.
Least privilege with a view. Create a view named user_directory that shows only id and username of users whose role is 'customer' (no emails, no staff or admin accounts). Then return everything from user_directory. In a server database you would GRANT SELECT on this view instead of on users.
You are the first backend developer at a food-delivery startup in Bengaluru. Choose the database(s) for: customer accounts and orders, payment records, restaurant search ("biryani near me" with typos), live rider locations, and monthly business reports. For each choice give one reason, and list three security rules you will follow from day one.
Which change actually prevents SQL injection in a login query?
Quick quiz
Read more (free)
Related help
Before this, learn
This topic builds on these. If something here feels new, open them first.
Related topics
- NoSQL: documents, key-value, wide-column and graphProcedures, triggers, SQL engines and NoSQL · same module
- MySQL vs PostgreSQL vs SQLite vs SQL ServerProcedures, triggers, SQL engines and NoSQL · same module
- SQL injection and how to stop itBackend Development · Backend security
- Managed relational databases: RDS and AuroraCloud Computing (AWS, Azure, Google Cloud) · Networking and databases: VPC and RDS
- SQL injection and safe queriesJava Programming (Core to Spring Boot) · JDBC, Maven, Gradle and JUnit
- SQL injection (SQLi)Ethical Hacking and Penetration Testing (legal labs) · Web attacks and their fixes
Questions people ask about this
Open a question to see the answer and why. The first ones are this topic's own quiz, so try the quiz above before you peek.
A new app needs users, orders and payments. What is the sensible default?
Answer: A relational database such as PostgreSQL or MySQL
Relational databases give transactions, constraints and joins; add others later for specific needs.
What does "least privilege" mean?
Answer: Each user or app gets only the rights it needs
Small rights mean small damage when an account is misused or leaked.
Why does typing ' OR '1'='1 into a careless login form return every row?
Answer: The quote ends the string early and OR '1'='1' is true for every row
The input becomes part of the SQL. Parameters keep input as data.
What is the best proof that your backups work?
Answer: Regularly restoring a backup to a test server and checking the data
Only a restore drill proves you can get the data back, and how long it takes.
Which job suits a search engine such as Elasticsearch or OpenSearch best?
Answer: Typo-tolerant product search with filters and ranking
Search engines use inverted indexes built for full-text search and relevance ranking.
What does "least privilege" mean for the app's database user?Related
Answer: It can only do what the app needs, nothing more
With only the needed rights, even a successful attack cannot drop tables or read unrelated data.
Reporting queries slow down your busy primary database. What helps most?Related
Answer: A read replica for the reports
Read replicas take read traffic off the primary. The Multi-AZ standby cannot serve reads.
What does "least privilege" mean for the app's database user?Related
Answer: It has only the permissions the app needs
Limits the damage if something goes wrong.
Parameterised queries protect you because input is…Related
Answer: Treated only as data, never as SQL code
The database treats placeholders' values as pure data.
From SQL injection (SQLi)
Pass the quiz (60% or more) or mark this topic as done when you are ready.
Your progress is saved on this device only.
Next steps
- This is the last topic of “Procedures, triggers, SQL engines and NoSQL”. The module exam comes next.
- Module 11 exam: procedures, triggers, engines and NoSQL · 13 questions · 25 min, without help. 6 topics of this module still to finish first.
- Then the next module, Interview questions and practice projects. 62 topics left in the course before the final exam.