Build the mental model
A database holds structured data - users, products, orders, posts, messages. Without one, an app could only serve static content.
Never give the browser direct database credentials
The real architecture is Browser -> Backend -> Database. If the frontend held production credentials, anyone could read or forge queries directly via developer tools.
- Relational (SQL) - tables with relationships, structured data
- Document (NoSQL) - flexible, JSON-like records
- Key-value - fast single-key lookups, often for caching
- Graph, time-series, search - specialized types for specific shapes
No database type is universally best - continue to the SQL, PostgreSQL, or MongoDB tutorials for query syntax and administration.
PROFILE PAGE LOAD SEQUENCE
--------------------------
PROFILE PAGE LOAD SEQUENCE
----------------------------
User opens profile page
|
v
Frontend requests profile data
|
v
Backend checks authentication ----> fails? reject, no query runs
|
v (authenticated)
Backend queries the database
|
v
Backend returns data to frontend
|
v
Frontend renders the profileConnect it to a real scenario
User opens profile
The user navigates to their profile page.
Frontend requests
The frontend sends a request for profile data to the backend.
Backend checks auth
The backend checks whether the request carries valid authentication.
Backend queries DB
Only if authenticated, the backend queries the database.
Backend returns data
The backend sends the data back to the frontend.
Frontend renders
The frontend renders the data as the profile page.
Authentication must be checked before the database is touched - otherwise data could be briefly exposed incorrectly.
Try the working example
const database = {
users: {
"user-1": { name: "Alice", email: "alice@example.com" },
"user-2": { name: "Bob", email: "bob@example.com" },
},
};
function getProfile(request) {
if (!request.authenticated) {
return { ok: false, error: "not authenticated - query never ran" };
}
const record = database.users[request.userId];
if (!record) {
return { ok: false, error: "user not found" };
}
return { ok: true, profile: record };
}
console.log("Authenticated request:", getProfile({ authenticated: true, userId: "user-1" }));
console.log("Unauthenticated request:", getProfile({ authenticated: false, userId: "user-1" }));Logs Alice's profile data for the authenticated request, and a 'not authenticated - query never ran' error for the unauthenticated one.5-minute try-it
Add a third user to the mock database and write a request for a userId that doesn't exist to see how the function handles a valid session but a missing record.
One important caution
Letting the browser hold direct, privileged database credentials instead of always routing data access through the backend.
Querying the database before checking authentication, which can briefly expose data to requests that should have been rejected.
Wikipedia - Database — How the Web Works