Skip to content

Spring Boot Projects for Your Portfolio: 8 Impressive Ideas

Purpose

I’ve hired developers and reviewed countless portfolios. Most fail because they showcase basic CRUD apps that anyone can build in a weekend. I want to share what actually impresses employers and demonstrate production-ready skills.

This post lists 8 Spring Boot projects that will make your portfolio stand out. These aren’t simple todo apps - they’re production-grade systems that demonstrate the skills employers actually care about in 2025: microservices architecture, security, scalability, and modern deployment practices.

What Makes a Spring Boot Project Impressive?

Before diving into the projects, let me clarify what distinguishes portfolio-worthy work from basic tutorials:

Production-ready features:

  • Proper authentication and authorization (JWT, OAuth2, RBAC)
  • Error handling and validation at every layer
  • Caching strategies for performance
  • Background job processing
  • API documentation (OpenAPI/Swagger)
  • Comprehensive test coverage (80%+)

Modern architecture patterns:

  • Microservices with service discovery
  • Event-driven communication
  • Clean architecture principles
  • Repository pattern implementation
  • SOLID principles in action

Real-world problem solving:

  • Handling concurrent access (distributed locks)
  • Managing large datasets (pagination, optimization)
  • Processing files efficiently (chunked uploads)
  • Real-time communication (WebSocket)
  • Search capabilities (Elasticsearch)

Clean code and documentation:

  • Clear README with architecture diagrams
  • API documentation with Postman collections
  • Database schema diagrams
  • Docker Compose for easy setup
  • Deployment guides

Deployment and DevOps:

  • Containerized with Docker
  • CI/CD pipeline (GitHub Actions)
  • Monitoring (Actuator, Prometheus)
  • Logging strategy
  • Environment-specific configuration

E-Commerce Microservices Platform

Why it impresses: Demonstrates microservices architecture, the most demanded skill in 2025.

Core features:

  • Product Service (catalog management with categories, variants, inventory)
  • Order Service (order processing workflow, status tracking)
  • Payment Service (Stripe/PayPal integration with webhooks)
  • Inventory Service (real-time stock management, reservations)
  • API Gateway (routing, rate limiting, authentication)
  • Service Discovery (Eureka for dynamic service registration)

Tech stack:

Spring Boot: 3.2+
Spring Cloud:
- Gateway (API routing, filters)
- Eureka (service discovery)
- Config Server (centralized configuration)
Security:
- Spring Security + JWT
- OAuth2 resource server
Data:
- PostgreSQL with Flyway migrations
- Redis for caching sessions and products
- RabbitMQ/Kafka for async messaging
Infrastructure:
- Docker Compose for local development
- Kubernetes deployment manifests

Advanced features that stand out:

  • Distributed tracing with Spring Cloud Sleuth + Zipkin
  • Circuit breakers with Resilience4j (prevent cascading failures)
  • Event-driven architecture (domain events for cross-service communication)
  • Saga pattern for distributed transactions (order orchestration)
  • Elasticsearch for product search with fuzzy matching

What employers look for:

// Demonstrate you understand:
// 1. Inter-service communication patterns
@FeignClient(name = "inventory-service")
public interface InventoryClient {
@PostMapping("/api/inventory/reserve")
InventoryReservation reserveStock(@RequestBody ReservationRequest request);
}
// 2. Data consistency across services
@KafkaListener(topics = "order-events")
public void handleOrderEvent(OrderEvent event) {
if (event.getType() == OrderEvent.Type.CANCELLED) {
inventoryService.releaseReservation(event.getOrderId());
}
}
// 3. Handling partial failures
@CircuitBreaker(name = "payment", fallbackMethod = "paymentFallback")
public PaymentResult processPayment(PaymentRequest request) {
return paymentService.charge(request);
}
private PaymentResult paymentFallback(PaymentRequest request, Exception e) {
return PaymentResult.failed("Payment service unavailable");
}

GitHub presentation tips:

  • Create separate repositories or use a monorepo with clear structure
  • Include Docker Compose for one-command startup
  • Add architecture diagram showing service interactions
  • Provide Postman collection for testing all APIs
  • Include screenshots of monitoring dashboards (Grafana)
  • Document the saga pattern with sequence diagrams

Social Media REST API

Why it impresses: Shows you can handle complex relationships and scale.

Core features:

  • User authentication (JWT + refresh token rotation)
  • Post creation with media upload (images, videos)
  • Comment system (nested replies, threading)
  • Like/unlike with real-time counters
  • Follow/unfollow users with feed generation
  • Timeline algorithm (mix of followed users’ content)
  • Hashtag search with trending topics
  • Notifications system (email + in-app)

Tech stack:

Backend:
- Spring Boot 3.x
- Spring Security (JWT + OAuth2 for social login)
- Spring Data JPA with Hibernate
- PostgreSQL for relational data
Storage:
- AWS S3 for media files (images, videos)
Real-time:
- WebSocket for live notifications
- Redis for session management and feed caching
Search:
- Elasticsearch for content and user search
Job Processing:
- Spring Batch for background tasks

Advanced features:

// Rate limiting per user
@RateLimiter(name = "api", fallbackMethod = "rateLimitFallback")
public ResponseEntity<Post> createPost(@RequestBody PostRequest request) {
// Implementation
}
// Content moderation with profanity filter
public Post createPost(PostRequest request) {
if (moderationService.containsProfanity(request.getContent())) {
throw new ContentModerationException("Content violates community guidelines");
}
// Create post
}
// Efficient feed generation (keyset pagination)
public Page<Post> getFeed(Long lastPostId, int limit) {
return postRepository.findByFollowedUsers(
getCurrentUserId(),
PageRequest.of(0, limit)
);
}

Database schema highlights:

-- Many-to-many relationship for followers
CREATE TABLE user_follows (
follower_id BIGINT REFERENCES users(id),
following_id BIGINT REFERENCES users(id),
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (follower_id, following_id)
);
-- Denormalization for performance
CREATE TABLE post_stats (
post_id BIGINT PRIMARY KEY REFERENCES posts(id),
likes_count INT DEFAULT 0,
comments_count INT DEFAULT 0,
shares_count INT DEFAULT 0
);
-- Indexes for efficient queries
CREATE INDEX idx_posts_user_created ON posts(user_id, created_at DESC);
CREATE INDEX idx_posts_hashtags ON posts(hashtags);

Task Management System (Kanban)

Why it impresses: Demonstrates state management and real-time collaboration.

Core features:

  • Board, list, and card management (drag-and-drop)
  • Team collaboration (invite members, permissions)
  • Labels, tags, due dates, and assignees
  • Checklists within cards with progress tracking
  • Activity feed and audit logs (who changed what)
  • File attachments to cards
  • Advanced search and filtering
  • Email notifications for due dates and mentions

Tech stack:

Backend:
- Spring Boot + Spring Web
- Spring Security (role-based access control)
Real-time:
- WebSocket (STOMP over WebSocket)
- SockJS fallback for older browsers
Data:
- PostgreSQL
- Hibernate Envers for audit logs
Scheduling:
- Quartz scheduler for due date reminders
- Spring Mail for email notifications
Frontend (optional):
- React/Vue.js with drag-and-drop library

Advanced features:

// Optimistic locking for concurrent edits
@Entity
public class Card {
@Version
private Long version; // Hibernate automatic versioning
private String title;
private String description;
// other fields
}
// Webhook integrations
public class WebhookService {
public void triggerWebhook(String eventType, Card card) {
webhookConfigurations.getActiveWebhooks(card.getBoardId())
.forEach(webhook -> {
HttpEntity<CardEvent> request = new HttpEntity<>(
new CardEvent(eventType, card)
);
restTemplate.postForEntity(webhook.getUrl(), request, Void.class);
});
}
}
// Custom fields per board (JSONB column)
@Entity
public class Card {
@Column(columnDefinition = "jsonb")
private Map<String, Object> customFields;
}

Real-Time Chat Application

Why it impresses: Shows you understand WebSocket and stateful connections.

Core features:

  • One-to-one messaging with delivery status
  • Group chats with member management
  • Online/offline status with last seen
  • Message read receipts
  • Typing indicators
  • Message history with infinite scroll pagination
  • File sharing (documents, images)
  • Push notifications for new messages
  • Emoji reactions on messages

Tech stack:

Backend:
- Spring Boot + WebSocket (STOMP protocol)
- Spring Security + JWT
State Management:
- Redis for session store and pub/sub
- Sticky sessions with load balancer
Data:
- MongoDB for message storage (document-oriented)
Storage:
- AWS S3 for file uploads
Client:
- React Native/Mobile app (optional)
- Web client with WebSocket support

Advanced features:

// WebSocket configuration
@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {
@Override
public void configureMessageBroker(MessageBrokerRegistry config) {
config.enableSimpleBroker("/topic");
config.setApplicationDestinationPrefixes("/app");
config.setUserDestinationPrefix("/user");
}
@Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry.addEndpoint("/ws")
.setAllowedOriginPatterns("*")
.withSockJS();
}
}
// Redis pub/sub for multi-instance deployment
@Service
public class MessageService {
@Autowired
private RedisTemplate<String, Message> redisTemplate;
public void sendMessage(Message message) {
// Save to MongoDB
messageRepository.save(message);
// Publish to Redis for other instances
redisTemplate.convertAndSend("messages", message);
}
@RedisListener(topic = "messages")
public void handleMessage(Message message) {
messagingTemplate.convertAndSend(
"/topic/chat." + message.getChatId(),
message
);
}
}
// Connection management
@Controller
public class PresenceController {
@EventListener
public void handleSessionConnected(SessionConnectedEvent event) {
// Update user's online status in Redis
StompHeaderAccessor accessor =
StompHeaderAccessor.wrap(event.getMessage());
String username = accessor.getUser().getName();
redisTemplate.opsForValue().set("online:" + username, "true");
}
}

Scalability demonstrated:

  • Sticky sessions configuration for load balancers
  • Redis pub/sub for multi-instance deployment
  • Connection pooling and cleanup strategies
  • Message ordering guarantees with sequence numbers

File Sharing Service

Why it impresses: Demonstrates cloud integration and handling large files.

Core features:

  • User authentication with quota management
  • File upload with drag-and-drop
  • Folder organization with nested structures
  • File sharing via public/private links
  • Expiring download links with time limits
  • File preview (images, PDF, videos)
  • Upload/download progress tracking
  • Storage quota management per user
  • Virus scanning with ClamAV integration

Tech stack:

Backend:
- Spring Boot 3.x
- Spring Security
Storage:
- AWS S3 or MinIO (self-hosted alternative)
Data:
- PostgreSQL for file metadata
Caching:
- Redis for frequently accessed metadata
Processing:
- Spring Batch for background processing
Frontend:
- Vue.js/React with upload component

Advanced features:

// Chunked upload for large files
@PostMapping("/upload/chunk")
public ResponseEntity<UploadChunkResponse> uploadChunk(
@RequestParam("file") MultipartFile chunk,
@RequestParam("uploadId") String uploadId,
@RequestParam("chunkNumber") int chunkNumber
) {
String chunkKey = "uploads:" + uploadId + ":" + chunkNumber;
s3Client.putObject(bucketName, chunkKey, chunk.getInputStream());
return ResponseEntity.ok(new UploadChunkResponse(chunkNumber, "uploaded"));
}
@PostMapping("/upload/complete")
public ResponseEntity<FileMetadata> completeUpload(
@RequestBody CompleteUploadRequest request
) {
// Combine chunks in S3
List<CompletableFuture<PartETag>> futures = request.getChunks().stream()
.map(chunk -> CompletableFuture.supplyAsync(() ->
s3Client.uploadPartCopy(bucketName, chunk.getKey(), ...)))
.collect(Collectors.toList());
CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])).join();
// Clean up chunks
request.getChunks().forEach(chunk -> s3Client.deleteObject(bucketName, chunk.getKey()));
return ResponseEntity.ok(fileMetadata);
}
// Thumbnail generation
@Async
public void generateThumbnail(FileMetadata file) {
if (file.getMimeType().startsWith("image/")) {
BufferedImage thumbnail = Thumbnails.of(file.getS3Key())
.size(200, 200)
.asBufferedImage();
String thumbnailKey = "thumbnails/" + file.getId();
s3Client.putObject(bucketName, thumbnailKey, thumbnail);
}
}

Booking/Reservation System

Why it impresses: Shows you can handle race conditions and business logic.

Core features:

  • Resource booking (rooms, equipment, appointments)
  • Calendar view with availability visualization
  • Time slot availability management
  • Conflict detection and prevention
  • Recurring bookings with complex patterns
  • Waitlist management for fully booked slots
  • Payment integration with deposits
  • Email/SMS reminders
  • Cancellation with refund logic

Tech stack:

Backend:
- Spring Boot
- Spring Security
Data:
- PostgreSQL with time-based partitioning
Concurrency:
- Redis for distributed locks
- Optimistic locking for database
Scheduling:
- Quartz scheduler for reminders
Payments:
- Stripe for payment processing
Notifications:
- Spring Mail + SendGrid
Frontend:
- FullCalendar.js for calendar UI

Advanced features:

// Distributed locking with Redis
@Service
public class BookingService {
@Autowired
private RedisTemplate<String, String> redisTemplate;
public Booking createBooking(BookingRequest request) {
String lockKey = "booking:resource:" + request.getResourceId() +
":slot:" + request.getTimeSlot();
// Try to acquire lock
Boolean acquired = redisTemplate.opsForValue()
.setIfAbsent(lockKey, "locked", Duration.ofSeconds(30));
if (!acquired) {
throw new SlotAlreadyBookedException();
}
try {
// Check availability again (double-check pattern)
if (bookingRepository.isSlotAvailable(request)) {
return bookingRepository.save(request.toBooking());
} else {
throw new SlotAlreadyBookedException();
}
} finally {
redisTemplate.delete(lockKey);
}
}
}
// Optimistic locking
@Entity
public class Booking {
@Id
private Long id;
@Version
private Long version; // Optimistic locking
private LocalDateTime startTime;
private LocalDateTime endTime;
// other fields
}
// Idempotent operations
@Service
public class PaymentService {
public PaymentResult processPayment(@Idempotent PaymentRequest request) {
String idempotencyKey = request.getIdempotencyKey();
// Check if already processed
return paymentRepository.findByIdempotencyKey(idempotencyKey)
.orElseGet(() -> {
// Process payment
PaymentResult result = stripeGateway.charge(request);
result.setIdempotencyKey(idempotencyKey);
return paymentRepository.save(result);
});
}
}

Analytics Dashboard

Why it impresses: Shows data processing and visualization skills.

Core features:

  • Data ingestion pipeline from multiple sources
  • Real-time metrics calculation
  • Custom dashboard creation
  • Multiple chart types (line, bar, pie, heatmap)
  • Date range filtering with time zone support
  • Export to CSV/PDF with custom formatting
  • Scheduled reports via email
  • Alert thresholds with notifications
  • Multi-tenant support with data isolation

Tech stack:

Backend:
- Spring Boot
- Spring Batch for ETL processes
Streaming:
- Apache Kafka for real-time data ingestion
Data:
- TimescaleDB/InfluxDB (time-series optimized)
- PostgreSQL for metadata
API:
- GraphQL for flexible querying
Caching:
- Redis for caching aggregations
Monitoring:
- Prometheus + Grafana
Frontend:
- React/Vue with D3.js or Chart.js

Advanced features:

// Caching strategies for different time ranges
@Service
public class MetricsService {
@Cacheable(value = "metrics", key = "#timeRange + '_' + #metric")
public MetricData getMetrics(TimeRange timeRange, String metric) {
// Real-time data (last hour) - no cache
// Recent data (last 24 hours) - 5 min cache
// Historical data - 1 hour cache
return metricsRepository.query(timeRange, metric);
}
}
// Background data refresh
@Scheduled(cron = "0 */15 * * * *") // Every 15 minutes
public void refreshAggregations() {
List<TimeRange> ranges = List.of(
TimeRange.LAST_HOUR,
TimeRange.LAST_24_HOURS,
TimeRange.LAST_7_DAYS
);
ranges.forEach(range -> {
AggregationData data = aggregationService.calculate(range);
cacheManager.put("metrics:" + range, data);
});
}
// Anomaly detection
@Service
public class AnomalyDetectionService {
public List<Anomaly> detectAnomalies(MetricData current) {
MetricData baseline = getBaseline(current.getMetric());
// Simple threshold-based detection
if (Math.abs(current.getValue() - baseline.getMean()) >
3 * baseline.getStandardDeviation()) {
return List.of(new Anomaly(
current.getMetric(),
current.getValue(),
"Value exceeds 3 standard deviations"
));
}
return List.of();
}
}

Job Board Platform

Why it impresses: Full-featured project with search and complex queries.

Core features:

  • Job posting with rich text editor
  • Job application with resume upload
  • Advanced search (filters, location radius, salary range)
  • Company profiles with multiple postings
  • Resume upload and parsing (Apache POI)
  • Application tracking with status workflow
  • Email alerts for new matching jobs
  • Saved searches with instant notifications
  • Interview scheduling with calendar integration
  • Payment for featured postings

Tech stack:

Backend:
- Spring Boot 3.x
Search:
- Elasticsearch for job search
Security:
- Spring Security + OAuth2 (LinkedIn, Google login)
Data:
- PostgreSQL for application data
- Redis for caching search results
Messaging:
- RabbitMQ for email queue
Monitoring:
- Spring Boot Actuator
Frontend:
- React.js with component library

Search implementation:

// Elasticsearch document mapping
@Document(indexName = "jobs")
public class JobDocument {
@Id
private String id;
@Field(type = FieldType.Text, analyzer = "standard")
private String title;
@Field(type = FieldType.Text, analyzer = "standard")
private String description;
@Field(type = FieldType.Keyword)
private List<String> skills;
@Field(type = FieldType.Integer)
private Integer salaryMin;
@Field(type = FieldType.Integer)
private Integer salaryMax;
@Field(type = FieldType.GeoPoint)
private GeoPoint location;
@Field(type = FieldType.Date)
private LocalDateTime postedDate;
}
// Search query with relevance scoring
@Service
public class JobSearchService {
public Page<JobDocument> search(JobSearchRequest request) {
BoolQueryBuilder query = QueryBuilders.boolQuery();
// Text search with boosting
if (request.getKeyword() != null) {
query.must(QueryBuilders.multiMatchQuery(request.getKeyword())
.field("title", 2.0f) // Boost title matches
.field("description", 1.0f)
.field("skills", 1.5f) // Boost skill matches
.fuzziness(Fuzziness.AUTO));
}
// Filters (no score impact)
if (request.getLocation() != null) {
GeoPoint center = new GeoPoint(request.getLat(), request.getLon());
query.filter(QueryBuilders.geoDistanceQuery("location")
.point(center)
.distance(request.getRadius() + "km"));
}
if (request.getSalaryMin() != null) {
query.filter(QueryBuilders.rangeQuery("salaryMax")
.gte(request.getSalaryMin()));
}
// Aggregations for faceted search
NativeSearchQueryBuilder searchQuery = new NativeSearchQueryBuilder()
.withQuery(query)
.withAggregation(AggregationBuilders.terms("by_company")
.field("companyId"))
.withAggregation(AggregationBuilders.range("salary_ranges")
.addField("salaryMin")
.addRange("0-50k", 0, 50000)
.addRange("50-100k", 50000, 100000)
.addRange("100k+", 100000, Integer.MAX_VALUE))
.withPageable(PageRequest.of(request.getPage(), request.getSize()));
return elasticsearchTemplate.queryForPage(searchQuery.build(), JobDocument.class);
}
}

Tech Stack That Impresses Employers

Must-have technologies:

  1. Spring Boot 3.x - Latest stable version
  2. Spring Security - Authentication/authorization
  3. Spring Data JPA - Database access
  4. PostgreSQL/MySQL - Production-grade databases
  5. Docker - Containerization
  6. Git - Version control with semantic commits

Differentiating technologies:

  1. Spring Cloud - Microservices (Gateway, Config, Discovery)
  2. Redis - Caching and session management
  3. RabbitMQ/Kafka - Message queues for async processing
  4. Elasticsearch - Full-text search capabilities
  5. AWS/GCP - Cloud service integration
  6. Kubernetes - Container orchestration
  7. GraphQL - API alternative to REST
  8. WebSocket - Real-time communication

Testing stack:

<!-- Unit and integration tests -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
<!-- Testcontainers for real Docker containers in tests -->
<dependency>
<groupId>org.testcontainers</groupId>
<artifactId>testcontainers</artifactId>
</dependency>
<!-- API testing -->
<dependency>
<groupId>io.rest-assured</groupId>
<artifactId>rest-assured</artifactId>
</dependency>
<!-- Code coverage -->
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
</plugin>

Testcontainers example:

@SpringBootTest
@Testcontainers
public class OrderServiceIntegrationTest {
@Container
static PostgreSQLContainer<?> postgres = new PostgreSQLContainer<>("postgres:15")
.withDatabaseName("testdb")
.withUsername("test")
.withPassword("test");
@Container
static GenericContainer<?> redis = new GenericContainer<>("redis:7-alpine")
.withExposedPorts(6379);
@DynamicPropertySource
static void configureProperties(DynamicPropertyRegistry registry) {
registry.add("spring.datasource.url", postgres::getJdbcUrl);
registry.add("spring.redis.host", redis::getHost);
registry.add("spring.redis.port", redis::getFirstMappedPort);
}
@Test
void shouldCreateOrder() {
// Test with real PostgreSQL and Redis
OrderRequest request = new OrderRequest("product-123", 2);
Order order = orderService.create(request);
assertThat(order.getId()).isNotNull();
assertThat(order.getStatus()).isEqualTo(OrderStatus.PENDING);
}
}

Monitoring and observability:

# Spring Boot Actuator
management:
endpoints:
web:
exposure:
include: health,metrics,prometheus
metrics:
export:
prometheus:
enabled: true
# Prometheus configuration
scrape_configs:
- job_name: 'spring-boot-app'
metrics_path: '/actuator/prometheus'
static_configs:
- targets: ['app:8080']

How to Present Projects on GitHub

README template:

# E-Commerce Microservices Platform
## Overview
Production-ready e-commerce platform built with Spring Boot microservices architecture. Handles 10K+ requests per second with distributed transactions and real-time inventory management.
## Tech Stack
- Spring Boot 3.2
- Spring Cloud (Gateway, Eureka, Config)
- PostgreSQL 15 + Redis 7
- RabbitMQ for messaging
- Docker + Kubernetes
## Features
- Microservices architecture (5 services)
- Distributed transactions with Saga pattern
- Real-time inventory management
- Elasticsearch product search
- JWT authentication
- Rate limiting and circuit breakers
- Distributed tracing with Zipkin
## Architecture
![Architecture Diagram](docs/architecture.png)
### Services
1. **Product Service** - Catalog management
2. **Order Service** - Order processing
3. **Payment Service** - Stripe integration
4. **Inventory Service** - Stock management
5. **API Gateway** - Routing and security
## Getting Started
### Prerequisites
- Java 17+
- Docker & Docker Compose
- Maven 3.8+
### Run Locally
```bash
git clone https://github.com/username/ecommerce-microservices.git
cd ecommerce-microservices
docker-compose up -d

Access: http://localhost:8080

API Documentation

Database Schema

Design your schema with primary keys, foreign keys, and indexes for performance.

Testing

Terminal window
mvn clean test

Coverage: 87% (Report)

Deployment

Docker

Terminal window
docker build -t ecommerce-app .
docker run -p 8080:8080 ecommerce-app

Kubernetes

Terminal window
kubectl apply -f k8s/

Live Demo

https://ecommerce-demo.example.com

Monitoring

Author

[Your Name] - LinkedIn

**What to include in your repository:**
1. Clear architecture diagram (use Mermaid or draw.io)
2. Postman collection for API testing
3. Docker Compose for one-command setup
4. Screenshots or video demo (3-5 minutes)
5. API documentation (Swagger/OpenAPI)
6. Database schema diagram
7. Test coverage report (Jacoco)
8. CI/CD pipeline (GitHub Actions workflow)
## Advanced Features That Make You Stand Out
**Security:**
```java
// JWT with refresh token rotation
@Service
public class TokenService {
public String generateAccessToken(User user) {
return Jwts.builder()
.setSubject(user.getEmail())
.claim("roles", user.getRoles())
.setIssuedAt(new Date())
.setExpiration(Date.from(Instant.now().plus(15, ChronoUnit.MINUTES)))
.signWith(secretKey)
.compact();
}
public String generateRefreshToken(User user) {
return Jwts.builder()
.setSubject(user.getEmail())
.setIssuedAt(new Date())
.setExpiration(Date.from(Instant.now().plus(7, ChronoUnit.DAYS)))
.signWith(secretKey)
.compact();
}
}
// Rate limiting per endpoint
@RateLimiter(name = "api", fallbackMethod = "rateLimitFallback")
@GetMapping("/api/search")
public ResponseEntity<List<Result>> search(@RequestParam String q) {
return ResponseEntity.ok(searchService.search(q));
}
// Input validation
@PostMapping("/api/users")
public ResponseEntity<User> createUser(@Valid @RequestBody CreateUserRequest request) {
// @Valid triggers validation based on annotations in the request DTO
}

Performance:

// Caching with Redis
@Cacheable(value = "products", key = "#id")
public Product getProductById(Long id) {
return productRepository.findById(id)
.orElseThrow(() -> new ProductNotFoundException(id));
}
@CachePut(value = "products", key = "#product.id")
public Product updateProduct(Product product) {
return productRepository.save(product);
}
// Pagination (keyset, not offset)
public Page<Product> getProducts(Long lastId, int limit) {
return productRepository.findByIdGreaterThanOrderByIdAsc(
lastId,
PageRequest.of(0, limit)
);
}
// N+1 prevention with entity graphs
@EntityGraph(attributePaths = {"category", "tags"})
List<Product> findAllWithDetails();

Code quality:

// Clean code: Single Responsibility Principle
@Service
public class OrderService {
private final OrderRepository orderRepository;
private final PaymentService paymentService;
private final InventoryService inventoryService;
private final NotificationService notificationService;
public Order createOrder(OrderRequest request) {
// Each service handles its own responsibility
}
}
// Global exception handling
@RestControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(ResourceNotFoundException.class)
public ResponseEntity<ErrorResponse> handleNotFound(ResourceNotFoundException ex) {
return ResponseEntity.status(HttpStatus.NOT_FOUND)
.body(new ErrorResponse("NOT_FOUND", ex.getMessage()));
}
@ExceptionHandler(MethodArgumentNotValidException.class)
public ResponseEntity<ErrorResponse> handleValidation(
MethodArgumentNotValidException ex
) {
Map<String, String> errors = ex.getBindingResult()
.getFieldErrors()
.stream()
.collect(Collectors.toMap(
FieldError::getField,
FieldError::getDefaultMessage
));
return ResponseEntity.badRequest()
.body(new ErrorResponse("VALIDATION_ERROR", errors));
}
}

Common Mistakes to Avoid

Don’t do this:

  • Basic todo app with no authentication
  • No error handling (generic 500 errors)
  • Hardcoded configuration values (API keys, URLs)
  • Missing test coverage
  • No deployment instructions
  • Poor Git commit messages (“fix bug”, “update”)
  • Inconsistent code style
  • Missing API documentation

Do this instead:

  • Implement proper authentication/authorization (JWT, OAuth2)
  • Global exception handling with custom error responses
  • Externalize configuration (Spring Cloud Config, environment variables)
  • 80%+ test coverage with unit and integration tests
  • Docker Compose + comprehensive deployment guide
  • Semantic commit messages (feat:, fix:, docs:)
  • Checkstyle/Spotless for consistent formatting
  • OpenAPI/Swagger documentation

What Employers Want

I’ve hired developers and reviewed hundreds of portfolios. Here’s what actually matters:

1. Production-ready code, not tutorials

  • Proper error handling and validation
  • Security best practices (no hardcoded secrets)
  • Database migrations (Flyway/Liquibase)
  • Logging strategy (not just System.out.println)
  • Configuration management

2. Demonstrate scalability awareness

  • Caching strategies (Redis, application-level)
  • Database optimization (indexes, query tuning)
  • Async processing for long-running tasks
  • Rate limiting and throttling
  • Horizontal scaling readiness

3. Show you can work in teams

  • Clean Git history with meaningful commits
  • Clear documentation (README, API docs)
  • Code reviews (show you accepted feedback)
  • CI/CD pipeline (automated testing and deployment)
  • Issue tracking (used GitHub Projects/Jira)

4. Solve real problems, not toy examples

  • Handle concurrent access (distributed locks)
  • Process large files (chunked uploads)
  • Implement search (Elasticsearch)
  • Real-time features (WebSocket)
  • Background jobs (scheduled tasks)

Summary

The best portfolio projects demonstrate production-ready skills, not just basic functionality. Focus on one or two complex projects rather than ten simple ones.

From my experience hiring, I recommend building:

If you want microservices experience:

  • E-Commerce Microservices Platform (Project 1)
  • Demonstrates service discovery, API gateway, distributed transactions

If you want real-time expertise:

  • Real-Time Chat Application (Project 4)
  • Shows WebSocket, Redis pub/sub, stateful connection management

If you want to showcase full-stack skills:

  • Social Media REST API (Project 2)
  • Job Board Platform (Project 8)
  • Complex queries, search integrations, OAuth2

If you want to highlight data processing:

  • Analytics Dashboard (Project 7)
  • Kafka streaming, time-series databases, aggregations

Pick a project that genuinely interests you and build it to production standards. That’s what impresses employers.

Final Words + More Resources

My intention with this article was to help others share my knowledge and experience. If you want to contact me, you can contact by email: Email me

Here are also the most important links from this article along with some further resources that will help you in this scope:

Oh, and if you found these resources useful, don’t forget to support me by starring the repo on GitHub!

Comments