Skip to content

Designing a Filterable Product API (Spring Boot System Design)

Designing an API to Filter Products by productType

Section titled “Designing an API to Filter Products by productType”
GET /api/products?productType=ELECTRONICS
@GetMapping("/products")
public List<Product> getProductsByType(@RequestParam String productType) {
return productService.getProductsByType(productType);
}

To return all products when productType isn’t supplied, make the parameter optional and branch on it:

@GetMapping("/products")
public List<Product> getProducts(
@RequestParam(required = false) String productType) {
return productType == null
? productService.getAllProducts()
: productService.findByProductType(productType);
}

This way GET /products and GET /products?productType=ELECTRONICS are both handled by the same endpoint.

public List<Product> getProductsByType(String productType) {
return productRepository.findByProductType(productType);
}
public interface ProductRepository extends JpaRepository<Product, Long> {
List<Product> findByProductType(String productType);
}
@Entity
public class Product {
@Id
@GeneratedValue
private Long id;
private String name;
private String productType;
}
  • Pagination
GET /products?productType=ELECTRONICS&page=0&size=20
  • Database index
CREATE INDEX idx_product_type ON product(product_type);
  • Redis caching
@Cacheable("products")
  1. Explain the API design.
  2. Discuss database indexing.
  3. Mention caching.
  4. Explain load balancing.
  5. Cover asynchronous processing.
  6. Mention monitoring and observability.
Topic Recommended Approach Full Coverage
Product filtering Repository query + index + pagination This page
High traffic scaling Horizontal scaling, caching, async processing Performance Optimization and Scalability
Distributed transactions Saga pattern Saga Pattern and Compensation Failures
Entity tracking Events or CDC (Debezium) Spring Boot Auditing
Centralized logging ELK stack + distributed tracing Microservices Communication Patterns
  • A filterable product API is a classic system-design warm-up: derived repository query, pagination, an index on the filtered column, and a caching layer on top.
  • Combine @RequestParam filtering with pagination (page/size) so result sets stay bounded as data grows.
  • Cache read-heavy, rarely-changing lookups like product listings with @Cacheable, backed by a database index on the filtered column.