Backend Interview Questions - Easy
Easy-level backend interview questions covering HTTP, REST APIs, databases, and server fundamentals.
Q1: What is REST and what are its principles?
Answer:
graph TB
A[REST<br/>Representational State Transfer] --> B[Stateless<br/>No session state]
A --> C[Client-Server<br/>Separation]
A --> D[Cacheable<br/>Responses]
A --> E[Uniform Interface<br/>Standard methods]
style A fill:#FFD700REST Principles
1. Stateless: Each request contains all information needed 2. Client-Server: Separation of concerns 3. Cacheable: Responses can be cached 4. Uniform Interface: Standard HTTP methods 5. Layered System: Client doesn't know if connected to end server 6. Code on Demand (optional): Server can send executable code
HTTP Methods (CRUD)
graph LR
A[CRUD] --> B[Create → POST]
A --> C[Read → GET]
A --> D[Update → PUT/PATCH]
A --> E[Delete → DELETE]
style A fill:#FFD700Example REST API:
1GET /api/users # List all users
2GET /api/users/123 # Get user by ID
3POST /api/users # Create new user
4PUT /api/users/123 # Update user (full)
5PATCH /api/users/123 # Update user (partial)
6DELETE /api/users/123 # Delete user
Q2: What are HTTP status codes and their meanings?
Answer:
graph TB
A[HTTP Status Codes] --> B[1xx Informational]
A --> C[2xx Success]
A --> D[3xx Redirection]
A --> E[4xx Client Error]
A --> F[5xx Server Error]
style A fill:#FFD700
style C fill:#90EE90
style E fill:#FFD700
style F fill:#FF6B6BCommon Status Codes
2xx Success:
200 OK: Request succeeded201 Created: Resource created204 No Content: Success, no body
3xx Redirection:
301 Moved Permanently: Resource moved302 Found: Temporary redirect304 Not Modified: Use cached version
4xx Client Error:
400 Bad Request: Invalid request401 Unauthorized: Authentication required403 Forbidden: No permission404 Not Found: Resource doesn't exist429 Too Many Requests: Rate limited
5xx Server Error:
500 Internal Server Error: Server error502 Bad Gateway: Invalid response from upstream503 Service Unavailable: Server overloaded504 Gateway Timeout: Upstream timeout
Q3: What is the difference between SQL and NoSQL databases?
Answer:
graph TB
subgraph SQL["SQL (Relational)"]
S1[Structured Schema]
S2[Tables & Rows]
S3[ACID Transactions]
S4[Vertical Scaling]
end
subgraph NoSQL["NoSQL (Non-Relational)"]
N1[Flexible Schema]
N2[Documents/Key-Value]
N3[BASE/Eventual Consistency]
N4[Horizontal Scaling]
endSQL Example (PostgreSQL)
1-- Create table
2CREATE TABLE users (
3 id SERIAL PRIMARY KEY,
4 name VARCHAR(100) NOT NULL,
5 email VARCHAR(100) UNIQUE NOT NULL,
6 created_at TIMESTAMP DEFAULT NOW()
7);
8
9-- Insert
10INSERT INTO users (name, email) VALUES ('Alice', 'alice@example.com');
11
12-- Query
13SELECT * FROM users WHERE email = 'alice@example.com';
14
15-- Join
16SELECT orders.*, users.name
17FROM orders
18JOIN users ON orders.user_id = users.id;
NoSQL Example (MongoDB)
1// Insert document
2db.users.insertOne({
3 name: "Alice",
4 email: "alice@example.com",
5 created_at: new Date(),
6 preferences: {
7 theme: "dark",
8 notifications: true
9 },
10 tags: ["premium", "verified"]
11});
12
13// Query
14db.users.findOne({ email: "alice@example.com" });
15
16// Update
17db.users.updateOne(
18 { email: "alice@example.com" },
19 { $set: { "preferences.theme": "light" } }
20);
When to Use Each
graph TB
A{Choose Database} --> B[Complex Relationships?]
A --> C[Need Transactions?]
A --> D[Flexible Schema?]
A --> E[Massive Scale?]
B -->|Yes| F[SQL]
C -->|Yes| F
D -->|Yes| G[NoSQL]
E -->|Yes| G
style F fill:#87CEEB
style G fill:#90EE90Q4: What is database indexing and why is it important?
Answer:
graph TB
A[Database Index] --> B[Faster Queries<br/>O log n vs O n]
A --> C[Trade-off<br/>Storage & write speed]
A --> D[B-Tree Structure<br/>Sorted data]
style A fill:#FFD700Without Index
sequenceDiagram
participant Q as Query
participant DB as Database
Q->>DB: SELECT * FROM users WHERE email = 'alice@example.com'
Note over DB: Full table scan
DB->>DB: Check row 1
DB->>DB: Check row 2
DB->>DB: Check row 3
DB->>DB: ... (1 million rows)
DB->>Q: Result (slow)With Index
sequenceDiagram
participant Q as Query
participant I as Index
participant DB as Database
Q->>I: SELECT * FROM users WHERE email = 'alice@example.com'
Note over I: Binary search in index
I->>I: Navigate B-tree
I->>DB: Get row at position X
DB->>Q: Result (fast)Creating Indexes
1-- Create index
2CREATE INDEX idx_users_email ON users(email);
3
4-- Composite index
5CREATE INDEX idx_users_name_email ON users(name, email);
6
7-- Unique index
8CREATE UNIQUE INDEX idx_users_email_unique ON users(email);
9
10-- Check query plan
11EXPLAIN SELECT * FROM users WHERE email = 'alice@example.com';
Trade-offs:
- ✅ Faster reads
- ❌ Slower writes (index must be updated)
- ❌ More storage space
Q5: What is authentication vs authorization?
Answer:
graph TB
A[Authentication] --> B[Who are you?<br/>Identity verification]
C[Authorization] --> D[What can you do?<br/>Permission check]
B --> E[Login credentials]
D --> F[Access control]
style A fill:#87CEEB
style C fill:#90EE90Authentication Flow
sequenceDiagram
participant U as User
participant S as Server
participant DB as Database
U->>S: POST /login<br/>{email, password}
S->>DB: Find user by email
DB->>S: User data
S->>S: Verify password hash
alt Valid credentials
S->>S: Generate JWT token
S->>U: 200 OK {token}
else Invalid credentials
S->>U: 401 Unauthorized
endAuthorization Flow
sequenceDiagram
participant U as User
participant S as Server
participant DB as Database
U->>S: GET /admin/users<br/>Authorization: Bearer <token>
S->>S: Verify token
S->>S: Extract user ID
S->>DB: Get user role
DB->>S: Role: "admin"
alt Has permission
S->>U: 200 OK {users}
else No permission
S->>U: 403 Forbidden
endImplementation Example
1package main
2
3import (
4 "context"
5 "encoding/json"
6 "net/http"
7 "strings"
8
9 "github.com/golang-jwt/jwt/v5"
10)
11
12type contextKey string
13
14const userContextKey contextKey = "user"
15
16// User represents authenticated user
17type User struct {
18 ID string `json:"id"`
19 Email string `json:"email"`
20 Role string `json:"role"`
21}
22
23// AuthMiddleware validates JWT token
24func AuthMiddleware(secretKey string) func(http.Handler) http.Handler {
25 return func(next http.Handler) http.Handler {
26 return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
27 authHeader := r.Header.Get("Authorization")
28 if authHeader == "" {
29 http.Error(w, `{"error":"No token provided"}`, http.StatusUnauthorized)
30 return
31 }
32
33 parts := strings.Split(authHeader, " ")
34 if len(parts) != 2 || parts[0] != "Bearer" {
35 http.Error(w, `{"error":"Invalid authorization header"}`, http.StatusUnauthorized)
36 return
37 }
38
39 token, err := jwt.Parse(parts[1], func(token *jwt.Token) (interface{}, error) {
40 return []byte(secretKey), nil
41 })
42
43 if err != nil || !token.Valid {
44 http.Error(w, `{"error":"Invalid token"}`, http.StatusUnauthorized)
45 return
46 }
47
48 claims, ok := token.Claims.(jwt.MapClaims)
49 if !ok {
50 http.Error(w, `{"error":"Invalid token claims"}`, http.StatusUnauthorized)
51 return
52 }
53
54 user := &User{
55 ID: claims["id"].(string),
56 Email: claims["email"].(string),
57 Role: claims["role"].(string),
58 }
59
60 ctx := context.WithValue(r.Context(), userContextKey, user)
61 next.ServeHTTP(w, r.WithContext(ctx))
62 })
63 }
64}
65
66// AuthorizeMiddleware checks user roles
67func AuthorizeMiddleware(allowedRoles ...string) func(http.Handler) http.Handler {
68 return func(next http.Handler) http.Handler {
69 return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
70 user, ok := r.Context().Value(userContextKey).(*User)
71 if !ok {
72 http.Error(w, `{"error":"Not authenticated"}`, http.StatusUnauthorized)
73 return
74 }
75
76 allowed := false
77 for _, role := range allowedRoles {
78 if user.Role == role {
79 allowed = true
80 break
81 }
82 }
83
84 if !allowed {
85 http.Error(w, `{"error":"Insufficient permissions"}`, http.StatusForbidden)
86 return
87 }
88
89 next.ServeHTTP(w, r)
90 })
91 }
92}
93
94// Usage
95func main() {
96 mux := http.NewServeMux()
97
98 // Protected admin endpoint
99 adminHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
100 json.NewEncoder(w).Encode(map[string]string{"message": "Admin access granted"})
101 })
102
103 mux.Handle("/admin/users",
104 AuthMiddleware("your-secret-key")(
105 AuthorizeMiddleware("admin")(adminHandler),
106 ),
107 )
108
109 http.ListenAndServe(":8080", mux)
110}
Q6: What is JWT (JSON Web Token)?
Answer:
graph TB
A[JWT] --> B[Header<br/>Algorithm & type]
A --> C[Payload<br/>Claims/data]
A --> D[Signature<br/>Verification]
style A fill:#FFD700JWT Structure
1eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
2
3[Header].[Payload].[Signature]
Header:
1{
2 "alg": "HS256",
3 "typ": "JWT"
4}
Payload:
1{
2 "sub": "1234567890",
3 "name": "John Doe",
4 "iat": 1516239022,
5 "exp": 1516242622
6}
Signature:
1HMACSHA256(
2 base64UrlEncode(header) + "." + base64UrlEncode(payload),
3 secret
4)
Creating and Verifying JWT
1package main
2
3import (
4 "errors"
5 "time"
6
7 "github.com/golang-jwt/jwt/v5"
8)
9
10type Claims struct {
11 UserID string `json:"userId"`
12 Email string `json:"email"`
13 Role string `json:"role"`
14 jwt.RegisteredClaims
15}
16
17// CreateToken generates a JWT token
18func CreateToken(user User, secretKey string) (string, error) {
19 claims := Claims{
20 UserID: user.ID,
21 Email: user.Email,
22 Role: user.Role,
23 RegisteredClaims: jwt.RegisteredClaims{
24 ExpiresAt: jwt.NewNumericDate(time.Now().Add(24 * time.Hour)),
25 IssuedAt: jwt.NewNumericDate(time.Now()),
26 },
27 }
28
29 token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
30 return token.SignedString([]byte(secretKey))
31}
32
33// VerifyToken validates and decodes a JWT token
34func VerifyToken(tokenString, secretKey string) (*Claims, error) {
35 token, err := jwt.ParseWithClaims(tokenString, &Claims{}, func(token *jwt.Token) (interface{}, error) {
36 return []byte(secretKey), nil
37 })
38
39 if err != nil {
40 return nil, err
41 }
42
43 if !token.Valid {
44 return nil, errors.New("invalid token")
45 }
46
47 claims, ok := token.Claims.(*Claims)
48 if !ok {
49 return nil, errors.New("invalid token claims")
50 }
51
52 return claims, nil
53}
54
55// Login handler example
56func LoginHandler(w http.ResponseWriter, r *http.Request) {
57 // Authenticate user (check credentials)
58 user := User{
59 ID: "123",
60 Email: "user@example.com",
61 Role: "admin",
62 }
63
64 token, err := CreateToken(user, "your-secret-key")
65 if err != nil {
66 http.Error(w, "Failed to create token", http.StatusInternalServerError)
67 return
68 }
69
70 json.NewEncoder(w).Encode(map[string]string{
71 "token": token,
72 })
73}
Q7: What is CORS and why is it needed?
Answer:
graph TB
A[CORS<br/>Cross-Origin Resource Sharing] --> B[Security Mechanism<br/>Browser protection]
A --> C[Same-Origin Policy<br/>Default restriction]
A --> D[Allow Cross-Origin<br/>Explicit permission]
style A fill:#FFD700Same-Origin Policy
graph LR
A[https://example.com] -->|✓ Same origin| B[https://example.com/api]
A -->|✗ Different port| C[https://example.com:8080]
A -->|✗ Different domain| D[https://api.example.com]
A -->|✗ Different protocol| E[http://example.com]
style B fill:#90EE90
style C fill:#FF6B6B
style D fill:#FF6B6B
style E fill:#FF6B6BCORS Flow
sequenceDiagram
participant B as Browser
participant S as Server
Note over B: Frontend at example.com
Note over S: API at api.example.com
B->>S: OPTIONS /api/users<br/>Origin: https://example.com
S->>B: 200 OK<br/>Access-Control-Allow-Origin: https://example.com<br/>Access-Control-Allow-Methods: GET, POST
B->>S: GET /api/users<br/>Origin: https://example.com
S->>B: 200 OK<br/>Access-Control-Allow-Origin: https://example.com<br/>{users}Implementing CORS
1package main
2
3import (
4 "net/http"
5 "strings"
6)
7
8// CORSMiddleware handles CORS headers
9func CORSMiddleware(allowedOrigins []string) func(http.Handler) http.Handler {
10 return func(next http.Handler) http.Handler {
11 return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
12 origin := r.Header.Get("Origin")
13
14 // Check if origin is allowed
15 allowed := false
16 for _, allowedOrigin := range allowedOrigins {
17 if allowedOrigin == "*" || allowedOrigin == origin {
18 allowed = true
19 break
20 }
21 }
22
23 if allowed {
24 w.Header().Set("Access-Control-Allow-Origin", origin)
25 w.Header().Set("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS")
26 w.Header().Set("Access-Control-Allow-Headers", "Content-Type, Authorization")
27 w.Header().Set("Access-Control-Allow-Credentials", "true")
28 }
29
30 // Handle preflight requests
31 if r.Method == http.MethodOptions {
32 w.WriteHeader(http.StatusOK)
33 return
34 }
35
36 next.ServeHTTP(w, r)
37 })
38 }
39}
40
41// Usage
42func main() {
43 mux := http.NewServeMux()
44
45 // Your handlers
46 mux.HandleFunc("/api/users", func(w http.ResponseWriter, r *http.Request) {
47 json.NewEncoder(w).Encode(map[string]string{"message": "Users endpoint"})
48 })
49
50 // Wrap with CORS middleware
51 handler := CORSMiddleware([]string{"https://example.com"})(mux)
52
53 http.ListenAndServe(":8080", handler)
54}
55
56// Simple CORS middleware (allow all)
57func SimpleCORSMiddleware(next http.Handler) http.Handler {
58 return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
59 w.Header().Set("Access-Control-Allow-Origin", "*")
60 w.Header().Set("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS")
61 w.Header().Set("Access-Control-Allow-Headers", "Content-Type, Authorization")
62
63 if r.Method == http.MethodOptions {
64 w.WriteHeader(http.StatusOK)
65 return
66 }
67
68 next.ServeHTTP(w, r)
69 })
70}
Q8: What is the difference between GET and POST?
Answer:
graph TB
subgraph GET
G1[Retrieve data]
G2[Parameters in URL]
G3[Cacheable]
G4[Idempotent]
G5[Bookmarkable]
end
subgraph POST
P1[Submit data]
P2[Parameters in body]
P3[Not cacheable]
P4[Not idempotent]
P5[Not bookmarkable]
endGET Request
1GET /api/users?page=1&limit=10 HTTP/1.1
2Host: api.example.com
3Authorization: Bearer <token>
1package main
2
3import (
4 "encoding/json"
5 "net/http"
6 "strconv"
7)
8
9// GET handler
10func GetUsersHandler(w http.ResponseWriter, r *http.Request) {
11 // Parse query parameters
12 pageStr := r.URL.Query().Get("page")
13 limitStr := r.URL.Query().Get("limit")
14
15 page, _ := strconv.Atoi(pageStr)
16 limit, _ := strconv.Atoi(limitStr)
17
18 if page == 0 {
19 page = 1
20 }
21 if limit == 0 {
22 limit = 10
23 }
24
25 // Fetch users from database
26 users := fetchUsers(page, limit)
27
28 w.Header().Set("Content-Type", "application/json")
29 json.NewEncoder(w).Encode(map[string]interface{}{
30 "users": users,
31 "page": page,
32 "limit": limit,
33 })
34}
POST Request
1POST /api/users HTTP/1.1
2Host: api.example.com
3Content-Type: application/json
4Authorization: Bearer <token>
5
6{
7 "name": "Alice",
8 "email": "alice@example.com"
9}
1package main
2
3import (
4 "encoding/json"
5 "net/http"
6)
7
8type CreateUserRequest struct {
9 Name string `json:"name"`
10 Email string `json:"email"`
11}
12
13type UserResponse struct {
14 ID string `json:"id"`
15 Name string `json:"name"`
16 Email string `json:"email"`
17}
18
19// POST handler
20func CreateUserHandler(w http.ResponseWriter, r *http.Request) {
21 var req CreateUserRequest
22
23 // Decode JSON body
24 if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
25 http.Error(w, "Invalid request body", http.StatusBadRequest)
26 return
27 }
28
29 // Validate
30 if req.Name == "" || req.Email == "" {
31 http.Error(w, "Name and email are required", http.StatusBadRequest)
32 return
33 }
34
35 // Create user in database
36 user := createUser(req.Name, req.Email)
37
38 w.Header().Set("Content-Type", "application/json")
39 w.WriteStatus(http.StatusCreated)
40 json.NewEncoder(w).Encode(UserResponse{
41 ID: user.ID,
42 Name: user.Name,
43 Email: user.Email,
44 })
45}
Comparison
| Feature | GET | POST |
|---|---|---|
| Purpose | Retrieve | Submit |
| Data location | URL | Body |
| Cacheable | Yes | No |
| Idempotent | Yes | No |
| Size limit | Yes (~2KB) | No |
| Visible in URL | Yes | No |
| Bookmarkable | Yes | No |
Q9: What is database normalization?
Answer:
graph TB
A[Normalization] --> B[Reduce Redundancy<br/>Eliminate duplicates]
A --> C[Improve Integrity<br/>Consistent data]
A --> D[Normal Forms<br/>1NF, 2NF, 3NF]
style A fill:#FFD700Unnormalized Data
1-- ❌ Redundant data
2CREATE TABLE orders (
3 order_id INT,
4 customer_name VARCHAR(100),
5 customer_email VARCHAR(100),
6 customer_address TEXT,
7 product_name VARCHAR(100),
8 product_price DECIMAL,
9 quantity INT
10);
11
12-- Problems:
13-- 1. Customer data repeated for each order
14-- 2. Product data repeated for each order
15-- 3. Update anomalies (change email in multiple places)
Normalized Data (3NF)
1-- ✅ Separate tables, no redundancy
2
3CREATE TABLE customers (
4 customer_id SERIAL PRIMARY KEY,
5 name VARCHAR(100),
6 email VARCHAR(100) UNIQUE,
7 address TEXT
8);
9
10CREATE TABLE products (
11 product_id SERIAL PRIMARY KEY,
12 name VARCHAR(100),
13 price DECIMAL
14);
15
16CREATE TABLE orders (
17 order_id SERIAL PRIMARY KEY,
18 customer_id INT REFERENCES customers(customer_id),
19 order_date TIMESTAMP DEFAULT NOW()
20);
21
22CREATE TABLE order_items (
23 order_item_id SERIAL PRIMARY KEY,
24 order_id INT REFERENCES orders(order_id),
25 product_id INT REFERENCES products(product_id),
26 quantity INT,
27 price_at_purchase DECIMAL
28);
Normal Forms
1NF (First Normal Form):
- Atomic values (no lists in cells)
- No repeating groups
2NF (Second Normal Form):
- 1NF + No partial dependencies
- Non-key attributes depend on entire primary key
3NF (Third Normal Form):
- 2NF + No transitive dependencies
- Non-key attributes depend only on primary key
Q10: What is caching and common caching strategies?
Answer:
graph TB
A[Caching] --> B[Faster Response<br/>Reduce load]
A --> C[Store Frequently<br/>Accessed Data]
A --> D[Multiple Levels<br/>Browser, CDN, Server]
style A fill:#FFD700Cache Layers
graph TB
A[User] --> B[Browser Cache]
B --> C[CDN Cache]
C --> D[Application Cache<br/>Redis, Memcached]
D --> E[Database]
style B fill:#FFE4B5
style C fill:#FFD700
style D fill:#87CEEB
style E fill:#90EE90Caching Strategies
1. Cache-Aside (Lazy Loading):
1package main
2
3import (
4 "context"
5 "encoding/json"
6 "fmt"
7 "time"
8
9 "github.com/redis/go-redis/v9"
10)
11
12type User struct {
13 ID string `json:"id"`
14 Name string `json:"name"`
15 Email string `json:"email"`
16}
17
18func GetUser(ctx context.Context, rdb *redis.Client, userID string) (*User, error) {
19 // Check cache first
20 cacheKey := fmt.Sprintf("user:%s", userID)
21 cached, err := rdb.Get(ctx, cacheKey).Result()
22
23 if err == nil {
24 // Cache hit
25 var user User
26 if err := json.Unmarshal([]byte(cached), &user); err == nil {
27 return &user, nil
28 }
29 }
30
31 // Cache miss: fetch from database
32 user, err := fetchUserFromDB(userID)
33 if err != nil {
34 return nil, err
35 }
36
37 // Store in cache
38 userData, _ := json.Marshal(user)
39 rdb.Set(ctx, cacheKey, userData, time.Hour)
40
41 return user, nil
42}
2. Write-Through:
1func UpdateUser(ctx context.Context, rdb *redis.Client, userID string, data User) (*User, error) {
2 // Update database
3 user, err := updateUserInDB(userID, data)
4 if err != nil {
5 return nil, err
6 }
7
8 // Update cache
9 cacheKey := fmt.Sprintf("user:%s", userID)
10 userData, _ := json.Marshal(user)
11 rdb.Set(ctx, cacheKey, userData, time.Hour)
12
13 return user, nil
14}
3. Write-Behind (Write-Back):
1func UpdateUserAsync(ctx context.Context, rdb *redis.Client, queue Queue, userID string, data User) error {
2 // Update cache immediately
3 cacheKey := fmt.Sprintf("user:%s", userID)
4 userData, _ := json.Marshal(data)
5 if err := rdb.Set(ctx, cacheKey, userData, time.Hour).Err(); err != nil {
6 return err
7 }
8
9 // Queue database update (async)
10 return queue.Enqueue("update-user", map[string]interface{}{
11 "userId": userID,
12 "data": data,
13 })
14}
Cache Invalidation
graph TB
A[Cache Invalidation] --> B[TTL<br/>Time-based expiry]
A --> C[Manual<br/>Explicit delete]
A --> D[Event-based<br/>On data change]
style A fill:#FFD700 1package main
2
3import (
4 "context"
5 "time"
6
7 "github.com/redis/go-redis/v9"
8)
9
10func CacheInvalidationExamples(ctx context.Context, rdb *redis.Client) {
11 // TTL (Time To Live)
12 rdb.Set(ctx, "key", "value", time.Hour) // Expires in 1 hour
13
14 // Manual invalidation
15 rdb.Del(ctx, "user:123")
16
17 // Pattern-based invalidation
18 keys, _ := rdb.Keys(ctx, "user:*").Result()
19 if len(keys) > 0 {
20 rdb.Del(ctx, keys...)
21 }
22
23 // Or use SCAN for large datasets (more efficient)
24 iter := rdb.Scan(ctx, 0, "user:*", 0).Iterator()
25 for iter.Next(ctx) {
26 rdb.Del(ctx, iter.Val())
27 }
28}
Summary
Key backend concepts:
- REST: Stateless, uniform interface, HTTP methods
- HTTP Status Codes: 2xx success, 4xx client error, 5xx server error
- SQL vs NoSQL: Relational vs document, ACID vs BASE
- Indexing: B-tree, faster queries, trade-offs
- Authentication vs Authorization: Identity vs permissions
- JWT: Token-based auth, stateless
- CORS: Cross-origin security, browser protection
- GET vs POST: Retrieve vs submit, idempotent vs not
- Normalization: Reduce redundancy, normal forms
- Caching: Strategies, invalidation, layers
These fundamentals are essential for backend development.
Related Snippets
- Backend Interview Questions - Hard
Hard-level backend interview questions covering distributed systems, advanced … - Backend Interview Questions - Medium
Medium-level backend interview questions covering microservices, advanced …