Following the user registration feature in Step 1, I moved on to the core feature of any SNS: The Feed.
However, simply storing and retrieving data isn't enough. I had to consider performance (how fast can we retrieve feeds?) and stability (how do we prevent abuse?).
In this post, I will share how I optimized database queries using Composite Indexes and implemented a custom Rate Limiter in Spring Boot.
1. Database Indexing Strategy
The most common query for a feed is: "Show me the latest posts written by User A."
Without an index, the database performs a Full Table Scan, checking every single row. To optimize this, I applied a Composite Index.
@Entity
@Table(name = "feeds", indexes = {
@Index(name = "idx_user_created_at", columnList = "user_id, created_at")
})
public class Feed { ... }
- Why user_id? To filter posts by the specific user.
- Why created_at? To sort them in descending order (latest first).
- Result: The database can now jump directly to the user's data and read it sequentially, significantly reducing query time.
2. Protecting the Server: Rate Limiting
One of the requirements was to limit users to 5 requests per minute to prevent spamming or DDoS-like behavior.
Instead of using heavy external tools like Redis immediately, I implemented a lightweight In-Memory Rate Limiter using Java's ConcurrentHashMap.
How it works:
- Storage: A Map stores the request count for each user ID.
- Check: Before processing a request, check if the count exceeds 5.
- Reset: A @Scheduled task clears the map every minute.
@Component
public class RateLimiter {
private final Map<Long, Integer> requestCounts = new ConcurrentHashMap<>();
public boolean isAllowed(Long userId) {
int count = requestCounts.getOrDefault(userId, 0);
if (count >= 5) return false; // Block request
requestCounts.put(userId, count + 1);
return true;
}
@Scheduled(cron = "0 * * * * *") // Reset every minute
public void resetCounts() {
requestCounts.clear();
}
}
3. Frontend Integration (React)
On the frontend, I handled the 429 Too Many Requests error gracefully. If the server rejects a request due to the rate limit, the user sees a friendly alert message instead of a crash.
} catch (error) {
if (error.response?.status === 429) {
alert("You are posting too fast! Please wait a moment. 🛑");
}
}
4. Conclusion
In this step, I learned that backend development is not just about logic, but about resource management.
- Indexes save CPU and I/O.
- Rate Limiters save the server from being overwhelmed.
Top comments (0)