مصاحبه طراحی سیستم
مصاحبه System Design: راهنمای قدمبهقدم برای قبولی
آمادگی برای مصاحبه System Design با یک فریمورک ۴۵ دقیقهای، مثال تخمین ظرفیت، اجزای کلیدی مثل cache و sharding، طراحی URL shortener و برنامه مطالعه.
فهرست مطالب
مصاحبه System Design قرار نیست بسنجد که معماری Netflix را حفظ کردهاید یا نه. هدفش این است که ببیند میتوانید یک مسئله مبهم را به نیازمندیهای مشخص تبدیل کنید و با استدلال به طراحیای برسید که بتوانید از trade-offهایش دفاع کنید. در این راهنما یک فریمورک تکرارپذیر برای جلسه ۴۵ تا ۶۰ دقیقهای، اجزای اصلیای که باید کامل بلد باشید، طراحی یک URL shortener بهعنوان مثال و یک برنامه مطالعه عملی را میخوانید.
مصاحبهکننده دقیقاً چه چیزی را ارزیابی میکند؟
بیشتر شرکتها برای System Design یک rubric تقریباً شبیه این دارند:
- محدودکردن مسئله (Scoping): آیا سوالهایی میپرسید که طراحی را تغییر میدهند (مقیاس، نسبت read به write، latency هدف، نیاز به consistency)، یا بلافاصله شروع به کشیدن باکس میکنید؟
- عمق فنی: وقتی مصاحبهکننده بیشتر میپرسد، میتوانید توضیح دهید یک جزء چطور کار میکند؟ «Kafka اضافه میکنیم» فقط یک اسم است؛ توضیح partitionها، consumer groupها و تضمین ترتیب پیامها یعنی عمق.
- استدلال درباره trade-off: هر انتخابی هزینه دارد. مصاحبهکننده میخواهد بشنود «X را به Y ترجیح میدهم چون نیازمندی Z را داریم، و هزینهاش W است.»
- ارتباط و هدایت جلسه: شما گفتگو را جلو میبرید، در نقاط کلیدی با مصاحبهکننده هماهنگ میشوید و وقتی مسیر را عوض میکند، خودتان را تطبیق میدهید.
- عملگرایی: برای مقیاس اعلامشده طراحی میکنید، یا یک ابزار داخلی ۱۰۰ نفره را به یک معماری multi-region تبدیل میکنید؟
معمولاً یک جواب درست وجود ندارد. دو کاندیدا میتوانند دو معماری متفاوت پیشنهاد دهند و هر دو نمره عالی بگیرند، چون نمره از استدلال میآید، نه از دیاگرام.
فریمورک قدمبهقدم برای مصاحبه ۴۵ تا ۶۰ دقیقهای
مدیریت زمان جایی است که خیلیها شکست میخورند. ۲۵ دقیقه روی نیازمندیها وقت میگذارند یا مستقیم سراغ schema دیتابیس میروند و هیچوقت به طراحی کلی نمیرسند. یک بودجه زمانی تقریبی:
| مرحله | زمان (۴۵ دقیقه) | خروجی |
|---|---|---|
| شفافسازی نیازمندیها | ۵ تا ۷ دقیقه | لیست functional و non-functional |
| تخمین ظرفیت | ۳ تا ۵ دقیقه | QPS، حجم ذخیرهسازی، پهنای باند |
| طراحی API | ۳ تا ۵ دقیقه | endpointهای اصلی |
| مدل داده | ۳ تا ۵ دقیقه | موجودیتها و انتخاب storage |
| طراحی سطح بالا | ۸ تا ۱۰ دقیقه | دیاگرام و مسیر درخواست |
| Deep dive | ۱۰ تا ۱۵ دقیقه | یک یا دو جزء با جزئیات |
| گلوگاهها و جمعبندی | ۳ تا ۵ دقیقه | ریسکها، trade-offها، قدمهای بعدی |
۱. شفافسازی نیازمندیها
نیازمندیها را به دو دسته تقسیم کنید و جایی بنویسید که مصاحبهکننده ببیند.
نیازمندیهای functional میگویند سیستم چه کاری انجام میدهد. لیست را کوتاه نگه دارید، سه تا پنج قابلیت اصلی، و صریحاً بگویید چه چیزی خارج از scope است: «کاربر لینک کوتاه میسازد و redirect میشود. alias دلخواه nice-to-have است. analytics خارج از scope است مگر اینکه بخواهید اضافهاش کنم.»
نیازمندیهای non-functional خیلی بیشتر از قابلیتها روی معماری اثر میگذارند:
- مقیاس: تعداد کاربر فعال روزانه، درخواست در ثانیه، رشد داده
- Latency: هدف p99 برای مسیر اصلی (مثلاً redirect زیر ۵۰ میلیثانیه)
- Availability: فرق 99.9% با 99.99% یعنی سطح افزونگی کاملاً متفاوت
- Consistency: قابل قبول است که یک آیتم تازهساختهشده یک ثانیه دیده نشود؟ برای موجودی حساب بانکی نه، برای تعداد لایک بله.
- Durability: آیا از دست رفتن داده هیچوقت قابل قبول است؟
یک سوال کلیدی: «سیستم read-heavy است یا write-heavy؟» همین یک جواب تصمیمهای caching، replication و storage را مشخص میکند.
۲. تخمین سرانگشتی (Back-of-the-Envelope)
در تخمین، مرتبه بزرگی مهم است نه دقت. اعداد را گرد کنید: یک روز حدود ۱۰۰ هزار ثانیه است (دقیقاً ۸۶٬۴۰۰) و این حساب ذهنی را ساده میکند. مثال برای URL shortener:
Assumptions
New URLs per day: 100 M
Read:write ratio: 100:1
Record size: ~500 bytes (short key, long URL, metadata)
Retention: 5 years
Write QPS
100 M / 86,400 s ≈ 1,200 writes/s (peak ×3 ≈ 3,500/s)
Read QPS
1,200 × 100 ≈ 120,000 reads/s (peak ≈ 350,000/s)
Storage
100 M × 365 × 5 ≈ 182 B records
182 B × 500 B ≈ 91 TB
Key space
Base62, 7 characters = 62^7 ≈ 3.5 trillion keys (enough for 182 B)
Cache (80/20 rule)
Assume ~1 B distinct URLs read per day, cache the hottest 20%
0.2 × 1 B × 500 B ≈ 100 GB → fits in a small Redis cluster
بعد بگویید این اعداد چه معنایی دارند: ۱۲۰ هزار read در ثانیه خیلی بیشتر از توان یک دیتابیس است، پس بیشتر readها باید از cache سرویس شوند؛ ۹۱ ترابایت روی یک ماشین جا نمیشود، پس به sharding نیاز داریم؛ ۳٬۵۰۰ write در ثانیه متوسط است و با یک storage شاردشده قابل مدیریت است.
دانستن اعداد کلاسیک latency هم کمک میکند، چون تصمیمهایی مثل «این را در حافظه cache کن» یا «روی مسیر اصلی درخواست cross-region نزن» را توجیه میکنند:
| عملیات | latency تقریبی |
|---|---|
| ارجاع به L1 cache | حدود ۱ نانوثانیه |
| ارجاع به حافظه اصلی (RAM) | حدود ۱۰۰ نانوثانیه |
| خواندن تصادفی از SSD | حدود ۲۰ تا ۱۰۰ میکروثانیه |
| رفتوبرگشت داخل یک دیتاسنتر | حدود ۰٫۵ میلیثانیه |
| خواندن ترتیبی ۱ مگابایت از SSD | حدود ۱ میلیثانیه |
| seek روی HDD | حدود ۱۰ میلیثانیه |
| رفتوبرگشت بین قارهای | حدود ۱۰۰ تا ۱۵۰ میلیثانیه |
۳. طراحی API
قبل از جزئیات داخلی، قرارداد را تعریف کنید. معمولاً دو سه endpoint کافی است:
POST /api/v1/urls
Body: { "longUrl": "https://...", "customAlias": "optional", "expiresAt": "optional" }
Response: 201 { "shortUrl": "https://sho.rt/aZ3kQ9x" }
GET /{shortKey}
Response: 301 or 302 redirect to longUrl
تصمیمها را همانجا بگویید: authentication (مثلاً API key برای ساخت لینک)، rate limiting برای هر کاربر، idempotency برای POSTهایی که retry میشوند، و pagination برای endpointهای لیستی. برای redirect، 301 اجازه میدهد مرورگر redirect را cache کند (بار کمتر، ولی آمار کلیک از دست میرود)، در حالی که با 302 هر کلیک از سرور شما رد میشود. این trade-off را بلند بگویید.
۴. مدل داده
موجودیتها و الگوهای دسترسی را مشخص کنید، بعد storage را انتخاب کنید. الگوی دسترسی از لیست موجودیتها مهمتر است: URL shortener فقط یک lookup با key دارد، بدون join و بدون range query. این ما را به سمت key-value یا wide-column store میبرد، هرچند یک دیتابیس رابطهای شاردشده هم جواب میدهد.
| معیار | SQL (PostgreSQL، MySQL) | NoSQL (DynamoDB، Cassandra، MongoDB) |
|---|---|---|
| Schema | سختگیرانه و اجباری | منعطف |
| Transaction | ACID کامل و چندسطری | معمولاً محدود به یک آیتم یا partition |
| Join | بهصورت native | معمولاً بهجایش denormalize میکنیم |
| مقیاسپذیری افقی | ممکن ولی پرزحمت (sharding، Vitess، Citus) | built-in |
| مناسب برای | داده رابطهای، کوئری پیچیده، یکپارچگی داده | الگوی دسترسی ساده، مقیاس خیلی بزرگ، write زیاد |
نگویید «NoSQL چون scale میشود». بگویید «الگوی دسترسی ما lookup با key با ۱۲۰ هزار read در ثانیه و ۹۱ ترابایت داده است و transaction چندسطری لازم نداریم، پس یک key-value store پارتیشنشده مناسب است.»
۵. طراحی سطح بالا
اجزای اصلی را بکشید و یک درخواست را از اول تا آخر دنبال کنید. اسکلت بیشتر سیستمهای وب این است: client → DNS/CDN → load balancer → سرورهای اپلیکیشن stateless → cache → دیتابیس، بهعلاوه workerهای async پشت یک صف. مسیر write و مسیر read را جدا توضیح دهید. اول ساده شروع کنید؛ پیچیدگی را در deep dive اضافه میکنید.
۶. Deep Dive
مصاحبهکننده معمولاً یکی دو بخش را انتخاب میکند، یا از شما میخواهد انتخاب کنید. گزینههای خوب بخشهایی هستند که بیشترین اثر را از نیازمندیهای non-functional میگیرند: تولید key، استراتژی caching، طرح sharding، یا مدیریت hot key. اینجا عمق شما دیده میشود: حالتهای خرابی، consistency حین replication، اینکه وقتی cache از دسترس خارج شد چه اتفاقی میافتد.
۷. گلوگاهها و Trade-offها
خودتان نقاط ضعف را پیدا کنید: single point of failure، partitionهای داغ، thundering herd هنگام cache miss، پرشدن صف. برای هرکدام راهحل پیشنهاد دهید و هزینهاش را بگویید.
۸. جمعبندی جلسه
طراحی را در کمتر از یک دقیقه خلاصه کنید، trade-offهای اصلی را دوباره بگویید و فهرست کنید با زمان بیشتر چه میکردید: monitoring و alerting، استقرار multi-region، جلوگیری از سوءاستفاده، بهینهسازی هزینه. یک جمعبندی روشن خیلی بهتر از تمامشدن وقت وسط جمله است.
اجزای اصلی که حتماً باید بلد باشید
نمیتوانید درباره trade-off بین اجزایی استدلال کنید که فقط اسمشان را میدانید. این حوزهها تقریباً در هر مصاحبهای مطرح میشوند. میتوانید دانشتان را با سوالات Scalability در DevTier محک بزنید.
Load Balancer
فرق L4 (لایه transport، مسیریابی بر اساس IP و پورت، خیلی سریع) و L7 (لایه application، مسیریابی بر اساس path، header یا cookie، امکان terminate کردن TLS) را بدانید. الگوریتمها را بشناسید: round robin، least connections، weighted و consistent hashing برای مسیریابی چسبنده به cacheها. health check و اینکه سرورهای اپلیکیشن باید stateless باشند (session در Redis یا توکن، نه در حافظه محلی) تقریباً همیشه مطرح است. خودتان را با سوالات Load Balancing سطح میدل بسنجید.
Caching و CDN
الگوها را بشناسید: cache-aside (اپ از cache میخواند، در صورت miss سراغ دیتابیس میرود و cache را پر میکند)، write-through، write-behind و پیامدهای هرکدام روی consistency. سیاستهای eviction (LRU، LFU، TTL) و خرابیهای کلاسیک را بدانید: cache stampede (miss همزمان تعداد زیادی درخواست برای یک key داغ؛ راهحل: request coalescing یا lock)، cache penetration (درخواست برای keyهایی که وجود ندارند؛ راهحل: negative caching یا Bloom filter) و داده کهنه. CDN محتوای استاتیک و قابل cache را در edgeهای نزدیک کاربر نگه میدارد و latency و بار روی origin را کم میکند. با سوالات Caching و CDN تمرین کنید.
Replication و Sharding
Replication داده را برای availability و مقیاسپذیری read روی چند نود کپی میکند. رایجترین مدل leader-follower است: writeها به leader میروند، readها میتوانند از followerها سرویس شوند و هزینهاش replication lag است. مدلهای multi-leader و leaderless (مبتنی بر quorum، مثل Cassandra) سادگی را با availability در write معاوضه میکنند.
Sharding داده را برای مقیاسپذیری write و storage بین نودها تقسیم میکند. استراتژیها را بدانید: range-based (مناسب range query، ولی خطر hot spot)، hash-based (توزیع یکنواخت، بدون range query) و consistent hashing (کمترین جابهجایی داده هنگام اضافهشدن نود). آماده باشید درباره انتخاب shard key، partition داغ و resharding صحبت کنید. این بخش را با سوالات Replication و Sharding سطح میدل تمرین کنید.
Consistency و CAP
قضیه CAP میگوید هنگام network partition، یک سیستم توزیعشده باید بین consistency و availability یکی را انتخاب کند. چون partition در عمل رخ میدهد، انتخاب واقعی بین رفتار CP و AP هنگام خرابی است. PACELC این را گسترش میدهد: حتی بدون partition هم بین latency و consistency معاوضه میکنید. طیف مدلها را بشناسید: strong، read-your-writes، monotonic reads، causal و eventual consistency، و بتوانید هر نیازمندی را به یک سطح مناسب نگاشت کنید. محاسبه quorum (یعنی R + W > N برای همپوشانی read و write) سوال تکمیلی رایجی است. کاندیداهای سینیور سراغ سوالات Consistency سطح سینیور بروند.
Message Queue و معماری Event-Driven
صفها (RabbitMQ، SQS) و logها (Kafka) producer و consumer را از هم جدا میکنند، جهش ترافیک را جذب میکنند و پردازش async را ممکن میکنند. delivery semantics (at-most-once، at-least-once، effectively-once) را بدانید، اینکه چرا consumer باید idempotent باشد، اینکه Kafka ترتیب را فقط داخل یک partition تضمین میکند، dead-letter queue و الگوهایی مثل transactional outbox برای انتشار مطمئن event بعد از write در دیتابیس. سوالات Event-Driven را ببینید.
الگوهای Reliability
- Retry با exponential backoff و jitter: از طوفان retryهای همزمان جلوگیری میکند.
- Timeout: هر فراخوانی شبکهای باید timeout داشته باشد؛ بدون آن، یک وابستگی کند thread pool شما را خالی میکند.
- Circuit breaker: فراخوانی وابستگی خراب را متوقف میکند، سریع fail میشود و بعد برای بازگشت آن را امتحان میکند.
- Rate limiting: با token bucket یا sliding window، معمولاً در API gateway و با شمارنده توزیعشده در Redis.
- Bulkhead: منابع را جدا میکند تا خرابی یک قابلیت کل سیستم را از کار نیندازد.
- Graceful degradation: بهجای خطا، cache کهنه یا نسخه محدودتری از قابلیت را سرویس میدهد.
اینها را با سوالات Reliability سطح سینیور بسنجید.
مثال عملی: طراحی URL Shortener در سطح بالا
با اعداد بخش تخمین (حدود ۱۲۰ هزار read در ثانیه، ۳٬۵۰۰ write در ثانیه در اوج و ۹۱ ترابایت در پنج سال)، طراحی اینطور شکل میگیرد.
تولید key جذابترین deep dive است. گزینهها:
۱. Hash کردن URL بلند (MD5 یا SHA-256 و برداشتن ۷ کاراکتر اول base62). ساده است، ولی collision باید تشخیص داده و retry شود، و یک URL بلند همیشه به یک key میرسد که ممکن است مطلوب باشد یا نباشد.
۲. شمارنده + encode به base62. یکتایی تضمینشده است، ولی یک شمارنده سراسری گلوگاه و single point of failure است. راهحل: هر سرور اپلیکیشن یک بازه ID (مثلاً بلوکهای ۱۰۰۰تایی) از یک سرویس هماهنگکننده مثل ZooKeeper یا یک sequence دیتابیس lease میکند. keyهای ترتیبی قابل حدساند؛ اگر مهم است، بیتها را shuffle کنید.
۳. سرویس تولید key از قبل. یک job پسزمینه keyهای تصادفی استفادهنشده را در یک pool میریزد و سرورها دستهای برمیدارند. write سریع است، به قیمت یک جزء اضافه.
مسیر write: client → load balancer → سرور اپ → گرفتن key از بازه ID محلی → نوشتن {key, longUrl, createdAt, expiresAt, userId} در key-value store شاردشده بر اساس key → برگرداندن لینک کوتاه.
مسیر read: client → CDN/edge (اختیاری برای لینکهای خیلی داغ) → load balancer → سرور اپ → Redis (cache-aside) → در صورت miss خواندن از دیتابیس و پرکردن cache → برگرداندن 302. با الگوی دسترسی 80/20، cache بخش عمده ۱۲۰ هزار read در ثانیه را جذب میکند.
Storage: یک key-value store پارتیشنشده (DynamoDB، Cassandra) با sharding بر اساس hash کلید و replication سهتایی. چون هر lookup فقط یک key است، کوئری cross-shard نداریم.
گلوگاهها و trade-offهایی که باید بگویید:
- یک لینک وایرال hot key میسازد. cache آن را مدیریت میکند و میتوانید برای keyهای خیلی داغ یک cache کوچک in-process روی سرورهای اپ اضافه کنید.
- Analytics نباید redirect را کند کند. eventهای کلیک را async به Kafka بفرستید و در یک pipeline جدا aggregate کنید.
- سوءاستفاده: rate limit روی ساخت لینک برای هر API key و بررسی URL با blocklist بدافزار.
- انقضا: حذف lazy هنگام read بهعلاوه یک job پاکسازی پسزمینه.
ارزش دارد چنین case studyهایی را بارها تمرین کنید. سوالات Case Study سطح سینیور را امتحان کنید تا ببینید در طراحی کامل چطور استدلال میکنید.
انتظارات چه فرقی دارد: میدل، سینیور و Staff
یک سوال ممکن است در همه سطوح پرسیده شود؛ چیزی که تغییر میکند معیار قبولی است.
مهندس میدل باید با کمی راهنمایی یک طراحی معقول و کارا ارائه دهد. باید اجزای اصلی را بشناسید، مقیاس را تقریبی تخمین بزنید و مسیر درخواست را توضیح دهید. اشکالی ندارد اگر مصاحبهکننده شما را به سمت deep diveهای مهم هل دهد. شروع با سوالات Scalability سطح جونیور و بعد رفتن به سطح میدل گرمکردن خوبی است.
مهندس سینیور باید مصاحبه را مستقل هدایت کند. بخشهای سخت را خودتان پیدا میکنید، روی حداقل یکی دو جزء عمیق میشوید، بدون اشاره مصاحبهکننده درباره حالتهای خرابی حرف میزنید و trade-offها را با عدد توجیه میکنید. باید با مدلهای consistency، اثر replication lag و مسائل عملیاتی مثل monitoring، deployment و migration داده راحت باشید.
مهندس Staff بر اساس وسعت دید و قضاوت در کل سیستم و سازمان ارزیابی میشود. انتظار بحث درباره تکامل طراحی در طول زمان (نسخه ۱ در برابر نسخه ۳)، استراتژی multi-region، هزینه، تصمیم build در برابر buy، مرز تیمها و مهاجرت از سیستم فعلی بدون downtime را داشته باشید. کاندیداهای Staff اغلب خود مسئله را بازتعریف میکنند: «واقعاً اینجا real-time لازم داریم، یا پنج دقیقه تأخیر یک طراحی خیلی سادهتر را ممکن میکند؟»
اشتباهات رایج
- پریدن به راهحل قبل از شفافسازی نیازمندیها؛ نتیجهاش طراحی سیستم اشتباه است.
- معماری پر از buzzword: اضافهکردن Kafka، Kubernetes و microservices بدون نیازمندیای که توجیهشان کند.
- نادیدهگرفتن اعداد: تخمین میزنید ولی هیچ تصمیمی را بر اساسش نمیگیرید.
- سکوت: مصاحبهکننده نمیتواند به استدلالی که نمیشنود نمره بدهد. بلند فکر کنید.
- صرف کل زمان روی یک جزء و هیچوقت نرسیدن به یک طراحی end-to-end.
- نگفتن trade-off: هر انتخاب را بدیهی جلوهدادن. کاندیداهای قوی نقطه ضعف طراحی خودشان را میگویند.
- نادیدهگرفتن خرابی: هیچوقت نپرسیدن «اگر این نود، این cache یا این region از کار بیفتد چه میشود؟»
- مقاومت در برابر راهنمایی مصاحبهکننده: وقتی مسیر را عوض میکند، معمولاً دلیلی دارد.
برنامه مطالعه عملی
با تلاش منظم، در حدود چهار تا شش هفته میتوانید به آمادگی خوبی برسید.
هفته ۱ و ۲: مبانی. هر یکی دو روز یک جزء را مطالعه کنید: load balancing، caching، دیتابیس و index، replication، sharding، consistency، صفها و الگوهای reliability. کتاب Designing Data-Intensive Applications نوشته Martin Kleppmann بهترین منبع برای عمق است. بعد از هر موضوع به سوالات تستی جواب دهید تا فاصله بین «دربارهاش خواندهام» و «میتوانم توضیحش بدهم» را پیدا کنید.
هفته ۳ و ۴: مسائل کلاسیک. سوالات رایج را حل کنید: URL shortener، rate limiter، news feed، سیستم چت، سرویس notification، file storage، web crawler و distributed cache. برای هرکدام کل فریمورک را در ۴۵ دقیقه روی کاغذ اجرا کنید و بعد با راهحلهای منتشرشده و engineering blogها مقایسه کنید (بلاگهای فنی شرکتهایی مثل Uber، Discord، Netflix و Stripe trade-offهای واقعی در مقیاس بالا را شرح میدهند).
هفته ۵ و ۶: مصاحبه آزمایشی. با یک همکار یا با ضبط صدای خودتان بلند تمرین کنید. زمان هر مرحله را بگیرید. مخصوصاً درباره هدایت گفتگو و بیان trade-offها بازخورد بخواهید، چون این مهارتها بیشترین پیشرفت را با تمرین دارند.
در تمام مدت: یک cheat sheet یکصفحهای با اعداد latency، میانبرهای تخمین و سوالاتی که همیشه در مرحله نیازمندیها میپرسید نگه دارید. جلسههای کوتاه و مکرر تستزدن از روزهای مطالعه طولانی و پراکنده مؤثرترند، چون spaced repetition است که مفاهیم را از «تشخیص» به «یادآوری» میبرد.
جمعبندی
قبولی در مصاحبه System Design به یک فرایند تکرارپذیر برمیگردد: نیازمندیها را شفاف کنید، مقیاس را تخمین بزنید، API و داده را تعریف کنید، طراحی سطح بالا را بکشید، جایی که مهم است عمیق شوید و درباره trade-offها صادق باشید. تعداد اجزای اصلی محدود است و استدلال با تمرین سریعتر میشود. دانشتان را در هر موضوع، از load balancing تا consistency، با آزمونهای رایگان System Design در DevTier محک بزنید و مرتب برگردید تا trade-offها بدون مکث به ذهنتان برسند.
این موضوعها را تمرین کن
مقالات دیگر
فرق مصاحبه جونیور، میدل و سینیور: از هر سطح چه انتظاری دارند؟
مصاحبه فنی جونیور، میدل و سینیور چه فرقی دارد؟ یک سؤال در سه عمق، انتظارات System Design و رفتاری، Red Flagها و اینکه برای کدام سطح اپلای کنید.
راهنمای کامل آمادگی مصاحبه بکاند: Node.js، API و دیتابیس
راهنمای کامل آمادگی مصاحبه بکاند: event loop در Node.js، طراحی API، دیتابیس SQL و NoSQL، کش با Redis، امنیت، message queue و برنامه ۴ هفتهای.
راهنمای کامل آمادگی مصاحبه فرانتاند: از جونیور تا سینیور
راهنمای کامل آمادگی مصاحبه فرانتاند: مراحل مصاحبه، انتظارات جونیور تا سینیور، پرتکرارترین سوالات جاوااسکریپت، ریاکت و Next.js و یک برنامه مطالعه ۴ هفتهای.