Your AI powered learning assistant

Frontend interview at Okko: System Design

Интро

00:00:00

From Coding Tasks to System Design: The News Aggregator Brief The path to a 400k offer moves to a second round centered on system design. The target product is a mobile‑first news aggregator with two screens: a feed and an article page. Tapping a card opens the full article, and each article can be liked or disliked. The score is a single rating that can go negative, effectively likes minus dislikes.

Core Features: Feed, Article View, and Reputation Score The core functional scope is minimal and clear: a news feed and a detailed article view. Clicking an item opens the article with title, image, and text. Users can apply a like or dislike, contributing to a unified rating value. The app is designed mobile first.

SEO-Driven Performance Priorities Search visibility is a must, so the architecture prioritizes SEO. Time to first paint is emphasized over time to interactive. Fast initial content, especially images in the feed, is important. Some interactivity latency is acceptable to keep crawlers effective.

Scope, Team, and Tech Stack Constraints Both frontend and backend facets are considered, without deep load modeling. The product targets the CIS region only, with future geo scalability in mind. Delivery is planned for roughly 3–5 months. React is the frontend framework, and Node powers the backend.

SSR with Next.js to Win SEO and Fast First Paint Server‑side rendering with Next.js is selected to produce crawlable HTML. Next acts as a BFF layer to orchestrate data fetching and templating. Pre‑rendered pages improve perceived speed and search indexing. This choice minimizes bespoke SSR complexity by using battle‑tested defaults.

Thin Client, SPA Hydration, and Trade-offs The client initially receives rendered HTML and then hydrates into an SPA. Time to interactive can be larger, but first paint is faster and bots parse content reliably. An alternative of bot‑only HTML with a pure SPA for users is rejected to avoid dual implementations. The single SSR+SPA path balances delivery speed and maintainability.

Backend, Database, and Image Storage Foundations A real backend on Node communicates with a database and serves JSON to the BFF. Images and other static assets live in S3‑like storage and are referenced by URL. The client downloads images directly from storage endpoints. This separation keeps media delivery efficient and scalable.

Geo Distribution with CDN and Horizontal Scalability A CDN caches static assets and even HTML to speed delivery across the CIS. Application servers are containerized for horizontal scaling. Databases scale separately and require more careful strategies. This layout makes regional performance tuning and capacity growth straightforward.

Choosing MongoDB for Flexible Content A document database like MongoDB fits the aggregator’s variable schemas. Optional fields and evolving article formats are easy to accommodate. Many Node developers are comfortable with documents, accelerating delivery. The current interface needs are met without heavy relational modeling.

User Model: Roles, Identity, and Liked Posts User has an id, a name, and a role such as reader or author, with a potential admin in the future. The model includes a list of liked post ids to enable personalization. Avatar can be a URL or a structured image object with multiple sizes. This keeps identity simple while enabling growth.

Post Model: Media, Markdown, Author, and Rating Post has an id, title, author userId, background image URL, and a numeric rating. Content is stored as a long Markdown string for flexible formatting. Images or avatars may be optional without breaking the schema. Aggregated articles are stored in our database rather than fetched on the fly.

Designing the Feed API with Pagination GET /posts returns a list of posts and supports pagination via a page number. Personalization can use cookies to tailor recommendations. The feed payload omits heavy fields when needed for speed. This keeps the list lightweight and fast to render.

User and Rating Endpoints with Single Source of Truth GET /user?id returns user details. A unified rate endpoint accepts postId and a plus or minus flag to like or dislike. The backend computes and returns the updated rating to avoid duplicated logic on the client. An unrate endpoint can remove a prior vote if needed.

Preventing Duplicate Votes and Handling Anonymous Users Each post’s voting state is a tri‑state: like, dislike, or none. The UI indicates the active state and disables repeated taps during requests. Anonymous users may vote with localStorage persistence and no guarantees beyond the device. The feed response can be enriched with per‑user like/dislike flags to avoid extra round‑trips.

Routing and Deferred Content Loading Strategy Routes include a feed and a per‑post page like /post/:id. To speed the initial feed, full article content is not sent with the list. A dedicated endpoint returns article content by id when the detail screen opens. Once fetched, content can be cached client‑side to skip re‑requests.

Security Baseline: Sanitization, CORS Allowlist, and CSP All text and media inputs are validated to block injections and malicious links. React/Next reduce many XSS risks, but backend allowlists add defense‑in‑depth. CORS is configured with an explicit list of trusted origins rather than wildcards. A strict Content‑Security‑Policy further mitigates unwanted embedding and script execution.

Lazy Loading the Feed with Scroll Anchors Lazy loading triggers when a sentinel element enters the viewport. The sentinel can be a hidden div or the last visible card’s image. As soon as it appears, the next page of posts is fetched and the sentinel advances. Triggering slightly before the bottom keeps scrolling continuous.

List Virtualization for Mobile Memory Limits Only render items within the visible window to keep the DOM small. Virtualization prevents jank and excessive memory use on mobile devices. Established React libraries make this straightforward to implement. This pairs well with pagination for smooth infinite scrolling.

Image Assets: S3 Links and Multi-Size Avatars Images are stored in S3‑like storage and accessed by direct links. Avatars may be represented as an object with sizes like XS, S, M, and L. Fields like images can be optional for users or posts. The approach supports future scaling and media optimizations.

Product Analytics via Metrica/GA and Custom Events Analytics integrate via Yandex.Metrica or Google snippets added to HTML. Custom events are instrumented where the business needs insight, such as like clicks. Teams get behavioral data without relying on user bug reports. This helps prioritize improvements based on real usage.

Client-Side Error Tracking and Session Traces Client errors are captured with tools like Sentry and similar services. JavaScript exceptions, network failures, and even session replays can be tracked. Access is limited to key staff to manage costs and noise. The result is faster detection and diagnosis of production issues.

Backend Observability: Trace IDs, Prometheus, Grafana A correlation id flows from client to BFF and backend to tie logs and traces together. This anticipates a future with multiple microservices and longer request chains. Metrics are scraped by Prometheus and visualized in Grafana dashboards. Failures and anomalies are surfaced before users report them.

Mobile-First Validation on Real Devices Performance is validated on actual phones, not just laptops. Mobile Safari gets special attention due to frequent quirks. Memory usage is profiled in devtools and with the React Profiler. Traffic is conserved by avoiding heavy content until it is needed.

Performance Metrics: Core Web Vitals and Lighthouse Core Web Vitals such as First Input Delay guide performance work. Lighthouse audits provide a quick, comparable snapshot. Too many metrics can distract, so signal is balanced with user feedback. A simple in‑product rating can capture perceived smoothness.

Real-User Measurements: FPS, Load Times, and Targets Smooth scrolling is measured via real‑user FPS derived from animation frames. A 60 FPS target indicates fluid interaction. Key flows like feed load and article open are timed from user action to fully rendered state. These custom metrics are sent to analytics for trend tracking.

A/B Testing with Feature Flags and Cohort Control Feature flags gate new functionality and manage rollouts. A flag service provides values to the client, enabling cohort‑based A/B tests. Results determine whether a change ships broadly or is reverted. Old flags are removed to prevent codebase clutter and if‑else sprawl.

Accessibility Practices and Screen Reader Semantics ARIA roles and attributes describe interactive elements to assistive tech. Elements hidden visually are removed from the DOM when appropriate, not just faded. Visual reversals that conflict with DOM order are avoided to keep reading order correct. Accessibility is verified through dedicated testing with screen readers.

CI Pipeline: Lint, Type-Check, Tests, Build GitLab CI runs linters, type checks, unit tests, and then the build for every merge request. Pipelines guard code quality before merges. Reproducible builds ensure consistent deployments. This keeps the development cadence reliable across contributors.

Trunk-Based Branching, Releases, and Stability Trunk‑based development keeps master as the single source of truth. Features live in short‑lived branches reviewed via merge requests. Master stays stable and always releasable. Release branches are cut from master when it’s time to ship.

Deploy Flow: Preview First, Then Controlled Production Rollout A deploy pipeline publishes to a preview environment for QA before production. Production releases are manually promoted. Rollout can start on one server to validate health, then expand to the fleet. Operations handle infrastructure and pipeline maintenance internally.

Testing Strategy: Unit and E2E to Aid QA Unit tests cover logic, with coverage targets as needed. End‑to‑end tests emulate real user scenarios in a headless browser. Automated suites support manual regression by QA. This collaboration raises confidence in each release.

Outcome and Next Steps The process advanced quickly, with an invitation to a final interview with the team lead. The journey toward the 400k offer continues. Follow along by liking and subscribing to catch the next stage. Until then, thanks and see you in the next update.