Functional Requirements:
Non-Functional Requirements:
1. Submit a User Review POST /v1/movies/{movie_id}/reviews
JSON
{
"rating": 8.5,
"comment": "Incredible cinematography and pacing.",
"userId": "uuid-1234"
}
Returns: 202 Accepted. The client application uses Optimistic UI to instantly recalculate and display the new average locally for the user, masking the backend processing time.
2. Search Movies GET /v1/movies/search?genre=Sci-Fi&min_rating=8.0&year=2026&page=1 Routed directly to the search engine.
3. Get Movie Details GET /v1/movies/{movie_id} Returns the movie metadata, the globally calculated average rating, and the AI-generated consensus summary.
Here is the refined mechanics of the real-time aggregation pipeline.
1. Continuous Stateful Aggregation (Apache Flink) We abandon time-based windows entirely. Flink consumes the movie_reviews_raw Kafka topic and utilizes Managed State.
currentTotalScore and totalReviewCount for every movieId.2. The JDBC Upsert Sink Flink's output is routed directly to the PostgreSQL Aggregate DB using a JDBC connector configured in Upsert mode.
INSERT ... ON CONFLICT DO UPDATE SQL command against the movieId primary key.3. Read Path and Search (Elasticsearch) When a user searches or filters movies, they never touch PostgreSQL or Cassandra.
genre=Sci-Fi AND rating > 8.0) using its optimized inverted indices, easily meeting the < 50ms latency requirement.