Thursday, February 12, 2026

Spring Boot: Security & Reliability

Spring Boot – Security & Reliability

1️⃣ JWT Authentication Flow

JWT (JSON Web Token) is a stateless authentication mechanism.

🔄 Flow

  1. Client sends login request (username + password)

  2. Spring Security authenticates user

  3. Server generates a JWT

  4. Client stores JWT (usually in memory or HttpOnly cookie)

  5. Client sends JWT in every request header:

    Authorization: Bearer <token>
    
  6. Server validates the token before processing request


🧱 Implementation Structure

  • SecurityConfig

  • JwtUtil

  • JwtFilter

  • UserDetailsService

  • Authentication Controller


🔹 Example: Security Configuration (Spring Boot 3)

@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
    http
        .csrf(csrf -> csrf.disable())
        .sessionManagement(session -> session
                .sessionCreationPolicy(SessionCreationPolicy.STATELESS))
        .authorizeHttpRequests(auth -> auth
                .requestMatchers("/auth/**").permitAll()
                .anyRequest().authenticated()
        );

    return http.build();
}

🔹 JWT Structure

JWT contains:

  • Header

  • Payload (username, roles, expiry)

  • Signature


⚠️ Best Practices

  • Keep token expiry short (15–60 min)

  • Use refresh tokens

  • Store secret securely (not hardcoded)

  • Always validate expiration


2️⃣ Role-Based Authorization

Authentication = Who are you?
Authorization = What can you do?


🔹 Define Roles

public enum Role {
    ROLE_USER,
    ROLE_ADMIN
}

🔹 Secure Endpoints

@PreAuthorize("hasRole('ADMIN')")
@GetMapping("/admin/data")
public String adminOnly() {
    return "Admin data";
}

🔹 Enable Method Security

@EnableMethodSecurity

🔐 Example Access Rules

.authorizeHttpRequests(auth -> auth
    .requestMatchers("/admin/**").hasRole("ADMIN")
    .requestMatchers("/user/**").hasAnyRole("USER", "ADMIN")
    .anyRequest().authenticated()
)

⚠️ Common Mistakes

❌ Forgetting ROLE_ prefix
❌ Not enabling method security
❌ Storing roles as plain strings without validation


3️⃣ Securing Endpoints Properly

🔹 Public vs Protected

Endpoint TypeExample
Public/auth/login
Protected/orders
Admin Only/admin/users

🔹 Additional Protections

  • Enable HTTPS (production mandatory)

  • Disable CSRF only for stateless APIs

  • Use CORS configuration carefully

  • Validate input (@Valid)


🔹 Global Exception Handling

@RestControllerAdvice
public class GlobalExceptionHandler {

    @ExceptionHandler(Exception.class)
    public ResponseEntity<String> handleException(Exception ex) {
        return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
                .body("Something went wrong");
    }
}

Prevents leaking internal stack traces.


4️⃣ Idempotent APIs (Prevent Data Corruption)

Idempotent = Multiple identical requests → same result.


🔹 Safe Methods (HTTP Standard)

MethodIdempotent?
GET✅ Yes
PUT✅ Yes
DELETE✅ Yes
POST❌ No (usually)

🔹 Example Problem

User clicks “Pay” button 3 times → 3 payments processed ❌


🔹 Solution 1: Idempotency Key

Client sends unique key:

Idempotency-Key: 12345-abc

Server:

  • Store key in DB

  • If same key comes again → return previous response


🔹 Solution 2: Database Constraints

Use:

  • Unique constraints

  • Optimistic locking (@Version)

  • Transactions


🔹 Optimistic Lock Example

@Version
private Long version;

Prevents lost updates.


🔹 Transaction Best Practice

@Transactional
public void transferMoney(...) {
    ...
}

Ensures atomicity.


🔥 Security & Reliability Checklist

Stateless authentication (JWT)
✅ Role-based access control
✅ Proper endpoint restrictions
✅ Input validation
✅ Global exception handling
✅ Idempotent critical operations
✅ Use transactions
✅ DB constraints


🚨 Real-World Failures You Avoid

  • Unauthorized data access

  • Privilege escalation

  • Duplicate payments

  • Lost updates

  • Data corruption

  • Session hijacking


 ADVANCED SECURITY (Beyond Basic JWT)

1️⃣ Refresh Token Strategy (Very Important)

Access Token → short life (15–30 mins)
Refresh Token → long life (7–30 days)

Why?

  • Limits damage if token is stolen

  • Better UX

Two approaches:

  • Store refresh token in DB

  • Store in Redis

  • Rotate refresh tokens (more secure)


2️⃣ Password Security

Never store ra

w passwords.

Use:

@Bean
public PasswordEncoder passwordEncoder() {
    return new BCryptPasswordEncoder();
}

BCrypt:

  • Automatically salts

  • Slow hashing (prevents brute force)


3️⃣ Rate Limiting (Prevent Brute Force / DDoS)

Protect:

  • /login

  • /register

  • /payment

Tools:

  • Bucket4j

  • Redis rate limiting

  • API Gateway throttling


4️⃣ CORS Proper Configuration

Bad CORS = anyone can call your API.

Example:

@Bean
public WebMvcConfigurer corsConfigurer() {
    return new WebMvcConfigurer() {
        public void addCorsMappings(CorsRegistry registry) {
            registry.addMapping("/**")
                    .allowedOrigins("https://yourfrontend.com")
                    .allowedMethods("GET", "POST", "PUT", "DELETE");
        }
    };
}

5️⃣ CSRF (When Needed)

  • Disable only for stateless APIs

  • Enable for session-based apps


6️⃣ Security Headers

Add:

  • HSTS

  • X-Content-Type-Options

  • X-Frame-Options

  • Content-Security-Policy

Spring Security handles many automatically.


🛡 RELIABILITY – More Than Idempotency

7️⃣ Circuit Breaker (Microservices)

If another service fails → prevent cascading failure.

Use:

  • Resilience4j

Prevents:

  • System-wide crash


8️⃣ Retry Mechanism

For temporary DB/network failures:

@Retryable(maxAttempts = 3)

9️⃣ Timeout Configuration

Never allow infinite waits.

Configure:

  • DB connection pool timeout

  • HTTP client timeout


🔟 Logging & Monitoring

You need:

  • Structured logging

  • Log levels

  • Correlation IDs

  • Metrics (Micrometer)

  • Health checks (/actuator/health)


1️⃣1️⃣ Audit Logging

Track:

  • Who changed data

  • When

  • What changed

Very important for financial systems.


1️⃣2️⃣ Database-Level Safety

  • Unique constraints

  • Foreign keys

  • Indexing

  • Proper isolation level

  • Avoid long transactions


🎯 Senior-Level Additions

  • OAuth2

  • OpenID Connect

  • API Gateway security

  • Token blacklisting (logout support)

  • Multi-factor authentication

  • Encryption of sensitive fields

  • Secure secrets management (Vault)


 

Thursday, February 5, 2026

Transactions & Performance (Spring Boot)

✅ Transactions & Performance — GOOD vs BAD Practices (with Examples)


1️⃣ Where to Put @Transactional

❌ BAD PRACTICE – Transaction in Controller

@RestController
public class OrderController {

    @Transactional
    @PostMapping("/order")
    public void placeOrder() {
        orderService.placeOrder();
    }
}

🚨 Why bad:

  • Controller shouldn’t manage transactions

  • Harder to test

  • Breaks separation of concerns


✅ GOOD PRACTICE – Transaction in Service

@Service
public class OrderService {

    @Transactional
    public void placeOrder() {
        orderRepo.save(order);
        stockRepo.updateStock();
    }
}

✔ Clean architecture
✔ Easier to manage & test


2️⃣ Transaction Scope (Length)

BAD – Long Transaction

@Transactional
public void processOrder() {
    callPaymentGateway();   // slow
    generateInvoicePdf();   // CPU heavy
    sendEmail();            // external I/O
    orderRepo.save(order);
}

🚨 Problems:

  • DB locks held too long

  • Poor throughput

  • Risk of deadlocks

  • Slow system under load


✅ GOOD – Short Transaction

public void processOrder() {
    callPaymentGateway();
    generateInvoicePdf();
    saveOrder();
}

@Transactional
void saveOrder() {
    orderRepo.save(order);
}

✔ Transaction only around DB work
✔ Better performance
✔ Scales well


3️⃣ Read APIs and Transactions

❌ BAD – No Read-Only Flag

@Transactional
public List<User> getUsers() {
    return userRepo.findAll();
}

🚨 Issues:

  • Unnecessary dirty checking

  • More memory usage


✅ GOOD – Read-Only Transaction

@Transactional(readOnly = true)
public List<User> getUsers() {
    return userRepo.findAll();
}

✔ Faster
✔ Optimized by Hibernate & DB


4️⃣ Exception Handling & Rollback

❌ BAD – Checked Exception Doesn’t Rollback

@Transactional
public void saveData() throws Exception {
    repo.save(entity);
    throw new Exception("Error"); // NO rollback!
}

🚨 Data gets committed unexpectedly.


✅ GOOD – Explicit Rollback Rule

@Transactional(rollbackFor = Exception.class)
public void saveData() throws Exception {
    repo.save(entity);
    throw new Exception("Error");
}

✔ Correct rollback behavior


5️⃣ Calling External Services in Transaction

❌ BAD

@Transactional
public void createUser() {
    userRepo.save(user);
    emailService.sendWelcomeMail(); // external call
}

🚨 Email failure can rollback DB
🚨 DB transaction waits on email server


✅ GOOD

@Transactional
public void createUser() {
    userRepo.save(user);
}

public void postCreateUser() {
    emailService.sendWelcomeMail();
}

✔ DB work isolated
✔ External failure doesn’t corrupt data


6️⃣ N+1 Query Problem

❌ BAD – N+1 Queries

List<Order> orders = orderRepo.findAll();

for (Order order : orders) {
    order.getItems().size(); // each call hits DB
}

🚨 1 + N queries → very slow


✅ GOOD – JOIN FETCH

@Query("SELECT o FROM Order o JOIN FETCH o.items")
List<Order> findAllWithItems();

✔ Single query
✔ Massive performance improvement


7️⃣ Pagination

❌ BAD – Load Everything

List<User> users = userRepo.findAll();

🚨 Memory heavy
🚨 Slow for large tables


GOOD – Pagination

Page<User> users = userRepo.findAll(PageRequest.of(0, 20));

✔ Faster
✔ Scalable


8️⃣ Transaction Propagation Misuse

❌ BAD – Everything in One Transaction

@Transactional
public void process() {
    saveMainData();
    saveAuditLog(); // should not rollback
}

🚨 Audit log lost if main tx fails


✅ GOOD – REQUIRES_NEW for Audit

@Transactional
public void process() {
    saveMainData();
    auditService.saveLog();
}

@Transactional(propagation = Propagation.REQUIRES_NEW)
public void saveLog() {
    auditRepo.save(log);
}

✔ Audit always saved
✔ Proper transaction boundaries


9️⃣ Overusing @Transactional

❌ BAD

@Transactional
public void calculate() {
    int x = a + b;
}

🚨 No DB → unnecessary overhead


✅ GOOD

public void calculate() {
    int x = a + b;
}

✔ Simple
✔ Clean


🔟 Fetch Strategy

❌ BAD – EAGER Loading

@OneToMany(fetch = FetchType.EAGER)
private List<Item> items;

🚨 Heavy queries
🚨 Hidden performance issues


✅ GOOD – LAZY + Fetch When Needed

@OneToMany(fetch = FetchType.LAZY)
private List<Item> items;

✔ Controlled loading
✔ Better performance


🧠 Senior Dev Summary (Memorable)

❝ Transactions protect data, but bad transactions kill performance ❞

Always remember:

  • Keep transactions short

  • DB work only

  • Read-only where possible

  • Avoid external calls

  • Watch N+1 queries


prevent hidden performance bugs and transactional issues before production.


1. @Transactional Pitfalls

Common Issues

  • Self-invocation

    • @Transactional methods called within the same class do not start a transaction.

    • Reason: Spring uses proxies.

  • Wrong layer

    • @Transactional on controllers → ❌

    • Correct place: Service layer

  • Exception handling

    • Rollback happens only for unchecked exceptions by default.

    • Catching exceptions without rethrowing → transaction commits.

  • Long transactions

    • Mixing DB logic with external API calls causes locks and timeouts.

Best Practices

  • Keep transactions short

  • One business use-case per transaction

  • Use rollbackFor when needed

  • Use REQUIRES_NEW only when truly required


2. Lazy vs Eager Loading

Default Behavior

  • @ManyToOne → EAGER

  • @OneToMany / @ManyToMany → LAZY

Common Problems

  • LazyInitializationException

  • Over-fetching with EAGER relationships

Correct Solutions

  • DTO projections (preferred)

  • JPQL fetch joins

  • EntityGraph for controlled loading

Anti-Patterns

  • Setting everything to FetchType.EAGER

  • Returning entities directly from controllers


3. Pagination & Filtering

Why It Matters

  • Prevents memory issues

  • Improves query performance

  • Protects APIs from abuse

Best Practices

  • Always use Pageable for list endpoints

  • Apply filtering at the database level

  • Index frequently filtered and sorted columns

Rules

  • Never return unbounded lists

  • Paginate before mapping to DTOs

  • Avoid in-memory filtering


4. N+1 Query Problem

What It Is

  • One query to fetch parent entities

  • N additional queries for related entities

How It Happens

  • Accessing lazy relationships in loops

  • Returning entities instead of DTOs

Detection

  • SQL logs

  • Hibernate statistics

  • Repeating queries with different IDs

Fixes

  • Fetch joins

  • DTO queries

  • Batch fetching

  • Entity graphs


5. Performance Awareness (Lead Expectations)

Red Flags in PRs

  • findAll() without pagination

  • Lazy collections accessed in loops

  • EAGER relationships on large entities

  • Business logic inside transactions

  • Controllers returning entities

Lead Rule

Every DB call must be intentional, bounded, and observable.


6️⃣ Transaction Isolation & Locking

Why it matters

Race conditions, double payments, dirty reads.

You should know

  • READ_COMMITTED (default in most DBs)

  • REPEATABLE_READ

  • SERIALIZABLE

Practical tools

  • Optimistic locking

@Version
private Long version;
  • Pessimistic locking

@Lock(LockModeType.PESSIMISTIC_WRITE)

Lead rule

If money or inventory is involved, locking must be explicit.


7️⃣ Flush vs Commit (Hibernate trap)

  • save() ≠ SQL execution

  • SQL runs on flush, not commit

repo.save(x);
repo.flush(); // forces SQL

Why this matters:

  • Constraint violations appear late

  • Bugs surface only at commit time


8️⃣ Read-only Transactions

@Transactional(readOnly = true)

Benefits:

  • Prevents accidental writes

  • Optimizes Hibernate dirty checking

Lead expectation:

  • All pure read service methods are read-only


9️⃣ Batch Operations & JDBC Performance

Problem

save() in loop → 1000 INSERTs

Solutions

  • Hibernate batch size

hibernate.jdbc.batch_size=50
  • saveAll()

  • Periodic flush() + clear()


🔟 Connection Pool Awareness (HikariCP)

You should understand:

  • Max pool size

  • Connection leaks

  • Long-running transactions blocking pool

Red flag:

App is “slow” but DB CPU is idle


1️⃣1️⃣ Index Awareness (Performance ≠ Code Only)

  • Index FK columns

  • Index columns used in:

    • WHERE

    • ORDER BY

    • JOIN

Lead rule:

Pagination without indexes is fake performance.


1️⃣2️⃣ Observability Basics

You should be able to:

  • Enable SQL logging temporarily

  • Spot N+1 in logs

  • Measure query time

  • Correlate API latency ↔ DB calls



Sunday, February 1, 2026

Spring Boot API Design & Architecture

 

 API Design & Architecture

Outcome: design clean, predictable, boring-in-a-good-way APIs


1️⃣ Controller–Service–Repository Separation

Controller (HTTP layer)

Responsibilities

  • Request/response mapping

  • Validation trigger

  • HTTP status codes

Rules

  • No business logic

  • No try/catch

  • No repository access

@PostMapping("/orders")
@ResponseStatus(HttpStatus.CREATED)
public OrderResponse create(@Valid @RequestBody CreateOrderRequest req) {
    return orderService.create(req);
}

Service (Business layer)

Responsibilities

  • Business rules

  • Transactions

  • Orchestration

Rules

  • No HTTP concepts

  • Throws domain exceptions

@Transactional
public OrderResponse create(CreateOrderRequest req) {
    if (!productExists(req.productId())) {
        throw new ResourceNotFoundException("Product not found");
    }
    return mapper.toResponse(orderRepo.save(mapper.toEntity(req)));
}

Repository (Data layer)

Responsibilities

  • DB access only

Rules

  • No business logic

  • No DTOs

Optional<Order> findById(Long id);

📌 Lead rule:

If it depends on HTTP → Controller
If it depends on DB → Repository
Everything else → Service


2️⃣ DTO vs Entity (Strict boundary)

Never expose Entities

Reasons:

  • DB coupling

  • Lazy loading issues

  • Security leaks

  • Versioning pain

✅ Use DTOs

Request DTO

record CreateOrderRequest(
    @NotNull Long productId,
    @Min(1) int quantity
) {}

Response DTO

record OrderResponse(
    Long id,
    int quantity,
    BigDecimal total
) {}

📌 Lead rule:

Entities never cross the service boundary


3️⃣ HTTP Status Codes (Intentional, not random)

CaseStatus
Create201 CREATED
Read / Update200 OK
Delete204 NO CONTENT
Validation error400 BAD REQUEST
Not found404 NOT FOUND
Duplicate409 CONFLICT
Auth required401
Forbidden403
Server error500

📌 Lead rule:

Status code tells the story before the body


4️⃣ Error Model (Single, consistent shape)

✅ Standard error response

{
  "timestamp": "2026-02-02T10:15:30",
  "status": 400,
  "error": "VALIDATION_ERROR",
  "message": "Invalid request",
  "path": "/orders",
  "details": {
    "quantity": "must be greater than 0"
  }
}

📌 Lead rule:

Errors are for machines first, humans second


5️⃣ Global Exception Handling

✅ Centralized handling

@RestControllerAdvice
public class GlobalExceptionHandler {

  @ExceptionHandler(MethodArgumentNotValidException.class)
  public ResponseEntity<ApiError> validation(...) {}

  @ExceptionHandler(ResourceNotFoundException.class)
  public ResponseEntity<ApiError> notFound(...) {}

  @ExceptionHandler(Exception.class)
  public ResponseEntity<ApiError> fallback(...) {}
}

Rules

  • No try/catch in controllers

  • Domain exceptions map to HTTP here

📌 Lead rule:

Controllers must be tiny and boring


6️⃣ Validation (Fail fast)

Bean Validation

@NotBlank
@Email
private String email;

Rules

  • Validation at DTO level

  • Service assumes valid input

  • Custom validators only when needed

📌 Lead rule:

Invalid data never reaches business logic


7️⃣ PR Review Checklist (Week 1)

Reject if you see

  • Entity in controller response

  • try/catch in controller

  • 200 for every response

  • Validation inside service

  • Repository logic in controller

Approve when

  • Thin controllers

  • Clear DTOs

  • Centralized errors

  • Correct status codes

  • Consistent error model


 Spring Boot API Design & Architecture

1️⃣ Package Structure (Feature-based, not layer-dump)

❌ Bad (layer-based)

controller/
service/
repository/
dto/

Good (feature-based)

user/
 ├─ UserController
 ├─ UserService
 ├─ UserRepository
 ├─ dto/
 │   ├─ CreateUserRequest
 │   ├─ UserResponse
 └─ exception/
     └─ UserNotFoundException

📌 Lead rule:

Features scale, layers rot.


2️⃣ Controller–Service–Repository (Spring way)

Controller

@RestController
@RequestMapping("/api/v1/users")
@RequiredArgsConstructor
public class UserController {

  private final UserService service;

  @PostMapping
  @ResponseStatus(HttpStatus.CREATED)
  public UserResponse create(@Valid @RequestBody CreateUserRequest req) {
    return service.create(req);
  }
}

Rules

  • @Valid only here

  • No try/catch

  • No entities


Service

@Service
@RequiredArgsConstructor
@Transactional
public class UserService {

  private final UserRepository repo;

  public UserResponse create(CreateUserRequest req) {
    if (repo.existsByEmail(req.email())) {
      throw new DuplicateResourceException("Email exists");
    }
    return UserMapper.toResponse(repo.save(UserMapper.toEntity(req)));
  }
}

Repository

public interface UserRepository extends JpaRepository<User, Long> {
  boolean existsByEmail(String email);
}

3️⃣ DTO vs Entity (Spring JPA safe)

❌ Entity

@Entity
class User {
  @Id @GeneratedValue
  Long id;
}

🚫 Never return this

DTO

public record UserResponse(
  Long id,
  String name,
  String email
) {}

📌 Rule:

Entity never leaves service layer.


4️⃣ Validation (Hibernate Validator)

public record CreateUserRequest(
  @NotBlank String name,
  @Email String email,
  @Size(min = 8) String password
) {}
  • Runs before the controller method

  • Fails fast with 400


5️⃣ Global Exception Handling (@RestControllerAdvice)

@RestControllerAdvice
public class GlobalExceptionHandler {

  @ExceptionHandler(MethodArgumentNotValidException.class)
  ResponseEntity<ApiError> handleValidation(MethodArgumentNotValidException ex) {
    return ResponseEntity.badRequest().body(ApiError.from(ex));
  }

  @ExceptionHandler(EntityNotFoundException.class)
  ResponseEntity<ApiError> handleNotFound(EntityNotFoundException ex) {
    return ResponseEntity.status(404).body(ApiError.notFound(ex));
  }
}

6️⃣ Standard Error Model

public record ApiError(
  Instant timestamp,
  int status,
  String error,
  String message,
  String path,
  Map<String, String> details
) {}

📌 Rule:

One error shape for the entire API.


7️⃣ HTTP Status Codes (Spring defaults)

CaseSpring
Create@ResponseStatus(CREATED)
Delete@ResponseStatus(NO_CONTENT)
ValidationMethodArgumentNotValidException
Not foundEntityNotFoundException
ConflictResponseStatusException(409)

8️⃣ Pagination (Spring Data)

@GetMapping
public Page<UserResponse> list(Pageable pageable) {
  return service.list(pageable);
}

Frontend-friendly, zero effort.


9️⃣ API Versioning

@RequestMapping("/api/v1/users")

📌 Never skip this.


🔟 Logging & Correlation ID (Must-have)

@Component
public class CorrelationIdFilter extends OncePerRequestFilter {
  protected void doFilterInternal(...) {
    MDC.put("correlationId", UUID.randomUUID().toString());
    filterChain.doFilter(req, res);
    MDC.clear();
  }
}

1️⃣1️⃣ Time & Serialization

spring:
  jackson:
    time-zone: UTC
    serialization:
      write-dates-as-timestamps: false

Always ISO-8601.


1️⃣2️⃣ OpenAPI / Swagger

springdoc-openapi-starter-webmvc-ui

Auto-docs your DTOs + validation.

📌 Rule:

Swagger is part of the API, not optional.


1️⃣3️⃣ Tests (Week-1 scope)

  • @WebMvcTest → controller

  • Plain JUnit → service

  • No DB in unit tests


 

LeetCode C++ Cheat Sheet June

🎯 Core Patterns & Representative Questions 1. Arrays & Hashing Two Sum – hash map → O(n) Contains Duplicate , Product of A...