Amazon Frontend Development Interview Questions & Answers
Curated interview practice questions with answers. These are practice scenarios, not a verified list of past interview questions.
About Amazon hiring for Frontend Development roles
Amazon is a global technology company spanning e-commerce, cloud computing through AWS, devices, advertising and streaming. In India it runs large engineering, operations and analytics teams supporting both Amazon.in and global businesses. It hires for software development engineers, SDETs, quality assurance engineers, business intelligence engineers, data engineers and data scientists.
For Frontend Development roles, this Amazon practice set focuses most on Frontend Architecture (5), TypeScript (5), Frontend Testing (5), CSS Architecture and Accessibility (5). It has 23 medium, 7 hard questions, so you can start easy and work up to the harder ones.
Company type
Product
Headquarters
Seattle, USA
Main India offices
Bengaluru, Hyderabad, Chennai, Pune, Gurugram
Amazon Frontend Development interview process
Online assessment (coding + work style survey)
Technical round 1 (DSA)
Technical round 2 (DSA or system design)
Bar raiser round
Hiring manager round
Typical pattern based on public candidate experiences. Rounds vary by role, team and year.
Solved for AmazonStart practicing
3 QUESTIONS FREESign up to unlock the full question bank and track your progress.Unlock every question and answer, then continue practising company-wise and package-wise.
Load flags once and check them where needed:
let flags = {};
export async function loadFlags(userId) {
const res = await fetch('/api/flags?user=' + encodeURIComponent(userId));
flags = res.ok ? await res.json() : {};
}
export const isEnabled = (name) => flags[name] === true;
// usage
await loadFlags(currentUser.id);
if (isEnabled('new-checkout')) renderNewCheckout();
else renderOldCheckout();
Defaulting to off when the request fails keeps the stable path. Flags enable gradual rollouts, but old flags must be removed to avoid clutter.
02
Errors from failed promises are silently disappearing in production. How do you catch them?
Promises without a catch produce unhandled rejections that do not stop the app but hide failures. I would add a global window.addEventListener('unhandledrejection') handler and window.onerror that report errors to a monitoring tool like Sentry with source maps. In code, every async call should have try and catch or a .catch, and ESLint rules such as no-floating-promises in TypeScript projects catch missing handlers.
03
A third-party library you need has no TypeScript types. What do you do?
First I check if types exist on DefinitelyTyped by installing @types/library-name. If not, I write a minimal declaration file, for example declare module 'old-chart-lib' with only the functions I use, in a types folder included by tsconfig. This is better than a blanket any import. If the library is important to the community, contributing those types upstream helps everyone.
04
TypeScript types say a field exists, but the app crashes because the API did not send it. How do you prevent this?
TypeScript only checks at compile time; it cannot guarantee what a server returns at runtime. I would validate responses at the boundary with a schema library like Zod or Valibot, deriving TypeScript types from the schema so they never drift. Invalid data then fails clearly with a logged error and a fallback UI. Generating types from OpenAPI specs also keeps frontend and backend contracts aligned.
05
Lighthouse shows a score of 95, but Search Console reports failing Core Web Vitals. Why?
Lighthouse is a single lab run on a simulated device, while Search Console uses field data from real Chrome users at the 75th percentile over 28 days. Real users may have slower phones, interact with the page, which affects INP and CLS later in the session, or see different content like ads and personalised blocks. I would add real user monitoring with attribution to find which pages and elements fail.
06
Detect offline status and retry queued requests when the connection returns.
Listen for online and offline events and keep a small queue:
const queue = [];
async function send(req) {
if (!navigator.onLine) { queue.push(req); showBanner('You are offline'); return; }
await fetch(req.url, req.options);
}
window.addEventListener('online', async () => {
hideBanner();
while (queue.length) await send(queue.shift());
});
window.addEventListener('offline', () => showBanner('You are offline'));
navigator.onLine can report true on captive networks, so treat failed fetches as offline too. Persist the queue in IndexedDB for reliability.
07
End-to-end tests fail randomly in CI about one run in five. How do you stabilise them?
I would collect traces, videos and screenshots of failures to see what actually happened. Usual fixes are replacing fixed waits with auto-waiting assertions, waiting for specific network responses, seeding isolated test data per test, mocking unstable third-party services, and disabling animations. I would quarantine persistently flaky tests with a tracking ticket rather than letting the team ignore red builds, and retry only as a temporary measure.
08
Model API request state with a discriminated union.
A shared status field lets TypeScript narrow each case:
type ApiState<T> =
| { status: 'idle' }
| { status: 'loading' }
| { status: 'success'; data: T }
| { status: 'error'; message: string };
function render(state: ApiState<string[]>) {
switch (state.status) {
case 'success': return state.data.join(', ');
case 'error': return 'Error: ' + state.message;
default: return 'Loading...';
}
}
Impossible states, like having both data and an error, cannot be represented.
09
How do you test code that depends on the current date or timers?
Real time makes tests slow and nondeterministic. I would use fake timers, such as vi.useFakeTimers() and vi.setSystemTime(new Date('2026-11-12T10:00:00+05:30')), then advance time with vi.advanceTimersByTime to test debounce, countdowns or expiry logic instantly. Restoring real timers after each test avoids leaking state. Designing functions to accept a clock or date parameter makes them even easier to test.
Snapshot tests save a component's rendered output and fail when it changes, which quickly detects unintended changes with little effort. However, large snapshots are hard to review, so developers often update them blindly, and they break on harmless markup changes. They work best for small, stable outputs like serialised config or error messages. For UI behaviour, explicit assertions on visible text and roles are more meaningful.
11
Which tsconfig options are important for a strict codebase?
strict: true enables a family of checks, including strictNullChecks and noImplicitAny, and should be on for new projects. noUncheckedIndexedAccess adds undefined to array and record lookups, catching many runtime errors. exactOptionalPropertyTypes, noImplicitOverride and noFallthroughCasesInSwitch add more safety. For bundler-based apps, moduleResolution: bundler, isolatedModules and verbatimModuleSyntax keep TypeScript aligned with how tools like Vite compile code.
12
How would you choose a frontend framework for a new project?
I would base it on project needs and team context rather than trends: team experience, hiring market in India, SEO and rendering requirements, ecosystem maturity, long-term support and performance on target devices. React has the largest ecosystem and talent pool, Angular suits large enterprise teams wanting an opinionated structure, Vue is approachable, and Svelte or Astro produce less JavaScript. A small proof of concept helps confirm the choice.
Tokens go in CSS with the @theme directive:
@import 'tailwindcss';
@theme {
--color-brand-500: #2563eb;
--color-brand-700: #1d4ed8;
--font-display: 'Poppins', sans-serif;
--radius-card: 12px;
}
/* usage in markup */
/* <button class='bg-brand-500 hover:bg-brand-700 rounded-card font-display'> */
Tailwind generates utilities like bg-brand-500 from these variables and also exposes them as CSS custom properties for use in plain CSS.
14
Users report errors you cannot reproduce. How do you set up frontend observability?
I would add an error monitoring tool like Sentry with uploaded source maps, release tags and user context such as browser and route, without personal data. Real user monitoring tracks Web Vitals and slow API calls. Breadcrumbs of clicks and network requests before an error help reproduce issues, and session replay with privacy masking shows what users saw. Alerts on error spikes after a release enable quick rollbacks.
15
Write a card that changes layout based on its container width.
Use a container query so the card adapts wherever it is placed:
.card-wrapper {
container-type: inline-size;
}
.card {
display: grid;
gap: 1rem;
}
@container (min-width: 420px) {
.card {
grid-template-columns: 160px 1fr;
align-items: center;
}
}
In a narrow sidebar the image stacks above text; in a wide main column it sits beside the text, with no viewport media queries.
16
Configure cache headers for hashed assets and HTML in Nginx.
Long cache for fingerprinted files, revalidation for HTML:
location ~* \.(js|css|woff2|avif|webp|svg)$ {
add_header Cache-Control 'public, max-age=31536000, immutable';
}
location / {
try_files $uri /index.html;
add_header Cache-Control 'no-cache';
}
This works only when build tools add content hashes to filenames. Returning users then load assets from cache instantly, while every deploy still reaches them through fresh HTML.
17
Tailwind classes built dynamically like 'bg-' + colour work locally but are missing in production. Why?
Tailwind finds classes by scanning source files for complete strings, so a class assembled at runtime never appears in the code and its CSS is not generated. The fix is to map values to full class names, such as const colours = { success: 'bg-green-600', error: 'bg-red-600' }. If truly dynamic values are needed, use inline styles with CSS variables or explicitly safelist those classes.
18
After a deployment, some users keep seeing the old version of your PWA. Why?
The old service worker is still controlling the page and serving cached files; a new worker waits until all tabs using the old one are closed. I would version the cache, delete old caches in the activate event, and show an 'Update available' prompt that calls skipWaiting and reloads. The sw.js file itself must be served with no-cache headers so browsers check for updates promptly.
19
Type checking takes several minutes in a large monorepo. How do you speed it up?
I would enable project references with composite builds so only changed packages are rechecked, and turn on incremental with build info files cached in CI. skipLibCheck avoids rechecking node_modules declarations. Very complex conditional types and huge unions slow the checker, so I would profile with --generateTrace and simplify hotspots. The bundler can use fast transpilation while type checking runs separately in parallel.
20
Several teams contribute CSS to one large app and styles keep breaking each other. What do you propose?
I would introduce scoping so styles cannot leak, using CSS Modules or a consistent naming convention per team, and organise global styles with cascade layers for reset, tokens, components and utilities. A shared design token set and component library reduces one-off styles. Linting with Stylelint, visual regression tests in CI and clear ownership of global files prevent new conflicts.
21
Compare CSS Modules, CSS-in-JS and utility-first CSS.
CSS Modules scope class names per file at build time, giving plain CSS with no runtime cost. CSS-in-JS libraries write styles in JavaScript with dynamic props, but runtime versions add bundle size and slow server rendering, so zero-runtime options are now preferred. Utility-first frameworks like Tailwind compose small classes in markup, producing small CSS and consistent spacing. The choice depends on team preference and rendering strategy.
22
Mock fetch in a Vitest test to check error handling.
Stub the global fetch and assert behaviour:
import { it, expect, vi, afterEach } from 'vitest';
import { loadCourses } from './api';
afterEach(() => vi.unstubAllGlobals());
it('returns an empty list when the server fails', async () => {
vi.stubGlobal('fetch', vi.fn().mockResolvedValue(
new Response('Server error', { status: 500 })
));
const result = await loadCourses();
expect(result).toEqual([]);
expect(fetch).toHaveBeenCalledWith('/api/courses');
});
For larger suites, MSW handlers are cleaner than stubbing fetch in every test.
Vitest reuses the Vite configuration and transform pipeline, so TypeScript, JSX, ES modules and path aliases work without separate Babel or ts-jest setup. It is fast thanks to on-demand transformation and smart watch mode, and its API is largely compatible with Jest, making migration easy. Jest remains mature and widely used, especially in projects not built with Vite. Both support mocking, snapshots and coverage.
24
What is the difference between lab data and field data in performance?
Lab data comes from controlled tests like Lighthouse or WebPageTest on a fixed device and network, which is great for debugging and comparing changes. Field data, or real user monitoring, comes from actual visitors through the Chrome UX Report or your own analytics, capturing real devices, networks and behaviour. Google ranks on field data. A page can score well in the lab but fail in the field on low-end phones.
25
Your app needs to support Hindi and English. How do you design internationalisation?
I would move all UI text into translation files keyed by message ids, use an i18n library that supports plurals and interpolation, and format numbers, dates and currency with Intl APIs for each locale, like en-IN and hi-IN. Layouts must handle longer text and Devanagari fonts with proper line height. The locale goes in the URL, such as /hi/, with hreflang tags for SEO and lang on html.
26
After a release, the app shows a blank page in some older browsers. What could be wrong?
The build probably targets newer syntax or uses an API that older browsers lack, causing a parse error that stops the whole bundle. I would check the console in that browser, compare the build target and browserslist with our support policy, and add missing polyfills for used APIs. Error monitoring with browser breakdowns catches this quickly, and testing on the oldest supported browser should be part of release checks.
27
The build works on your machine but fails in CI. How do you troubleshoot?
I would compare environments first: Node version, package manager version, and whether CI uses npm ci with the committed lockfile while I used npm install. Other common causes are case-sensitive file paths on Linux, missing environment variables, and files ignored by Git. Pinning Node with an .nvmrc or engines field and reproducing the CI command locally in a clean clone or container usually reveals the difference.
Throttle allows a function to run at most once in a given interval:
function throttle(fn, wait) {
let last = 0;
return function (...args) {
const now = Date.now();
if (now - last >= wait) {
last = now;
fn.apply(this, args);
}
};
}
window.addEventListener('scroll', throttle(updateProgressBar, 100));
Unlike debounce, which waits for calls to stop, throttle fires regularly during continuous events such as scrolling or dragging.
29
Parsing a 30 MB JSON response freezes the page for seconds. How do you fix it?
JSON.parse runs on the main thread, so a huge payload blocks rendering and input. The best fix is to avoid sending that much: paginate, filter on the server or request only needed fields. If the data is truly needed, parse and process it inside a Web Worker and send back only what the UI needs, or stream it with NDJSON and process chunks. Compression reduces transfer time but not parse time.
30
Write a minimal observable store in plain JavaScript.
A store holds state and notifies subscribers:
function createStore(initial) {
let state = initial;
const listeners = new Set();
return {
get: () => state,
set(update) {
state = { ...state, ...update };
listeners.forEach(fn => fn(state));
},
subscribe(fn) {
listeners.add(fn);
return () => listeners.delete(fn);
}
};
}
const cart = createStore({ items: 0 });
const stop = cart.subscribe(s => (badge.textContent = s.items));
cart.set({ items: 2 });
The returned unsubscribe function prevents memory leaks.
Tips to crack the Amazon Frontend Development interview
Prepare STAR-format stories for each Amazon Leadership Principle, such as Customer Obsession, Ownership and Dive Deep.
Practise medium-level DSA problems on arrays, trees, graphs and dynamic programming, explaining time and space complexity aloud.
For BIE or data roles, practise SQL window functions and metric-driven case questions on e-commerce funnels and delivery operations.
Keep a one-minute story ready for every project on your CV: problem, your part, tools, result.
Practise the hard questions on this page aloud; Amazon interviewers usually ask follow-ups on your first answer.
Frequently asked questions
How many rounds are there in the Amazon Frontend Development interview?
Candidates usually go through 5 stages: Online assessment (coding + work style survey); Technical round 1 (DSA); Technical round 2 (DSA or system design); Bar raiser round; Hiring manager round. The exact rounds change with the role, team, location and your experience, so confirm the process with the recruiter.
Which topics should I prepare for the Amazon Frontend Development interview?
This practice set leans on Frontend Architecture (5), TypeScript (5), Frontend Testing (5), CSS Architecture and Accessibility (5). Revise those first, then practise explaining one or two of your own projects end to end, because most Amazon interviewers ask you to walk through real work.
Are these the exact questions asked at Amazon?
No. These are curated practice questions that match the skills and difficulty usually tested in product interviews like Amazon's. They are not a leaked or verified list of past questions.
Where does Amazon hire Frontend Development professionals in India?
Amazon has large teams in Bengaluru, Hyderabad, Chennai, Pune, Gurugram. Openings and locations change often, so check the Amazon careers page and filter by city and experience.
Frontend Development questions for similar companies