tesco logo

Tesco Interviews

4 experiences114 reads9 questions50% success rate
tesco interview experience
tesco logo
Tesco
May 9, 20253 reads

Summary

This post details a system design interview experience at Tesco, where I was tasked with building a real-time analytics dashboard backend service that integrates data from multiple disparate internal services, handles various data formats and reliability issues, and provides an aggregated API endpoint.

Full Experience

You're developing a backend service for a real-time analytics dashboard that tracks user interactions across an e-commerce platform. Your service needs to:

  • Process incoming event data from multiple sources
  • Perform aggregation operations
  • Provide API endpoints for the frontend dashboard with summarized data (given below)

Core Requirements:

Your service needs to fetch and combine data from three internal data sources:

  • User Activity Service: Tracks page views, clicks, and session data
  • Transaction Service: Tracks purchases, cart additions, and checkout events
  • Inventory Service: Tracks product stock levels and alerts

Note that each service has different response characteristics, data formats, and reliability issues:

/**
 * Fetches recent user activity data
 * Returns detailed user interaction events
 * High volume data, occasionally returns partial results
 * ~150ms average response time with occasional spikes
 */
async function fetchUserActivity(timeWindow) {
    return new Promise((resolve, reject) => {
        const delay = 100 + Math.random() * 100; // 100-200ms
        setTimeout(() => {
            if (Math.random() < 0.15) {
                // Sometimes returns partial data with an error flag
                resolve({
                    events: generateRandomEvents(Math.floor(Math.random() * 10) + 5),
                    complete: false,
                    error: "Service degraded, partial data returned"
                });
            } else if (Math.random() < 0.05) {
                // Occasionally fails completely
                reject(new Error("User activity service temporarily unavailable"));
            } else {
                resolve({
                    events: generateRandomEvents(Math.floor(Math.random() * 20) + 10),
                    complete: true
                });
            }
        }, delay);
    });
function generateRandomEvents(count) {
    const events = [];
    const eventTypes = ["page_view", "click", "scroll", "search"];

    for (let i = 0; i < count; i++) {
        events.push({
            eventId: `evt-${Math.random().toString(36).substring(2, 10)}`,
            userId: `user-${Math.floor(Math.random() * 1000)}`,
            type: eventTypes[Math.floor(Math.random() * eventTypes.length)],
            timestamp: Date.now() - Math.floor(Math.random() * 60000),
            data: {
                page: Math.random() < 0.5 ? "/products" : "/checkout",
                duration: Math.floor(Math.random() * 300)
            }
        });
    }
    return events;
}

}

/**

  • Fetches recent transaction data

  • Returns financial transaction information

  • Slower but fairly reliable service

  • Data format differs from user activity */ async function fetchTransactions(timeWindow) { return new Promise((resolve, reject) => { const delay = 200 + Math.random() * 150; // 200-350ms setTimeout(() => { if (Math.random() < 0.08) { reject(new Error("Transaction service unavailable")); } else { const transactions = []; const count = Math.floor(Math.random() * 8) + 2;

             for (let i = 0; i < count; i++) {
                 transactions.push({
                     transactionId: `tx-${Date.now()}-${Math.random().toString(36).substring(2, 7)}`,
                     customerData: {
                         id: `user-${Math.floor(Math.random() * 1000)}`,
                     },
                     amount: +(Math.random() * 200 + 10).toFixed(2),
                     status: Math.random() < 0.9 ? "completed" : "pending",
                     items: Math.floor(Math.random() * 5) + 1,
                     createdAt: new Date(Date.now() - Math.floor(Math.random() * 3600000)).toISOString()
                 });
             }
             resolve({
                 data: transactions,
                 meta: {
                     total: transactions.length,
                     timeframe: timeWindow
                 }
             });
         }
     }, delay);
    

    }); }

/**

  • Fetches inventory status updates

  • Returns stock level alerts and changes

  • Fast but returns data in a completely different structure */ async function fetchInventoryAlerts(urgencyLevel = "all") { return new Promise((resolve, reject) => { const delay = 50 + Math.random() * 100; // 50-150ms setTimeout(() => { if (Math.random() < 0.1) { reject(new Error("Inventory service connection refused")); } else { // Returns XML-like string that needs parsing const alertCount = Math.floor(Math.random() * 5); let xmlResponse = &lt;inventory-alerts generated="${new Date().toISOString()}" count="${alertCount}"&gt;;

             for (let i = 0; i < alertCount; i++) {
                 const productId = Math.floor(Math.random() * 1000);
                 const currentStock = Math.floor(Math.random() * 10);
                 const threshold = 5;
                 const urgency = currentStock < 2 ? "high" : "medium";
    
                 if (urgencyLevel === "all" || urgencyLevel === urgency) {
                     xmlResponse += `
             &lt;alert type="stock" urgency="${urgency}"&gt;
               &lt;product id="${productId}" /&gt;
               &lt;current-stock&gt;${currentStock}&lt;/current-stock&gt;
               &lt;threshold&gt;${threshold}&lt;/threshold&gt;
               &lt;location warehouse="${Math.floor(Math.random() * 5) + 1}" /&gt;
             &lt;/alert&gt;
           `;
                 }
             }
    
             xmlResponse += '&lt;/inventory-alerts&gt;';
             resolve(xmlResponse);
         }
     }, delay);
    

    }); }

Task:

Create an Express.js API endpoint that:

  • Implements a GET /api/dashboard endpoint that accepts a timeWindow query parameter (e.g., "15m", "1h", "24h")
  • Fetches data from all three services concurrently
  • Handles the different response formats, error scenarios, and partial data
  • Aggregates the data into a unified dashboard response
  • Implements proper timeout handling (maximum 300ms total response time)

Sample response :

{
"dashboard": {
"timeWindow": "15m", // or whatever was requested
"summary": {
"activeUsers": 42,
"revenueTotal": 1234.56,
"conversionRate": 2.7,
"inventoryAlerts": 3
},
"details": {
"userActivity": {
// Processed user activity data
"complete": true|false,
// Additional details
},
"transactions": {
// Processed transaction data
// Additional details
},
"inventory": {
// Processed inventory data
// Additional details
}
},
"status": {
"servicesResponded": ["userActivity", "transactions", "inventory"],
"servicesFailed": [],
"responseTime": 298
}
}
}

Interview Questions (1)

Q1
Real-time Analytics Dashboard Backend Service
System DesignHard

You're developing a backend service for a real-time analytics dashboard that tracks user interactions across an e-commerce platform. Your service needs to:

  • Process incoming event data from multiple sources
  • Perform aggregation operations
  • Provide API endpoints for the frontend dashboard with summarized data (given below)

Core Requirements:

Your service needs to fetch and combine data from three internal data sources:

  • User Activity Service: Tracks page views, clicks, and session data
  • Transaction Service: Tracks purchases, cart additions, and checkout events
  • Inventory Service: Tracks product stock levels and alerts

Note that each service has different response characteristics, data formats, and reliability issues:

/**
 * Fetches recent user activity data
 * Returns detailed user interaction events
 * High volume data, occasionally returns partial results
 * ~150ms average response time with occasional spikes
 */
async function fetchUserActivity(timeWindow) {
    return new Promise((resolve, reject) => {
        const delay = 100 + Math.random() * 100; // 100-200ms
        setTimeout(() => {
            if (Math.random() < 0.15) {
                // Sometimes returns partial data with an error flag
                resolve({
                    events: generateRandomEvents(Math.floor(Math.random() * 10) + 5),
                    complete: false,
                    error: "Service degraded, partial data returned"
                });
            } else if (Math.random() < 0.05) {
                // Occasionally fails completely
                reject(new Error("User activity service temporarily unavailable"));
            } else {
                resolve({
                    events: generateRandomEvents(Math.floor(Math.random() * 20) + 10),
                    complete: true
                });
            }
        }, delay);
    });
function generateRandomEvents(count) {
    const events = [];
    const eventTypes = ["page_view", "click", "scroll", "search"];

    for (let i = 0; i < count; i++) {
        events.push({
            eventId: `evt-${Math.random().toString(36).substring(2, 10)}`,
            userId: `user-${Math.floor(Math.random() * 1000)}`,
            type: eventTypes[Math.floor(Math.random() * eventTypes.length)],
            timestamp: Date.now() - Math.floor(Math.random() * 60000),
            data: {
                page: Math.random() < 0.5 ? "/products" : "/checkout",
                duration: Math.floor(Math.random() * 300)
            }
        });
    }
    return events;
}

}

/**

  • Fetches recent transaction data

  • Returns financial transaction information

  • Slower but fairly reliable service

  • Data format differs from user activity */ async function fetchTransactions(timeWindow) { return new Promise((resolve, reject) => { const delay = 200 + Math.random() * 150; // 200-350ms setTimeout(() => { if (Math.random() < 0.08) { reject(new Error("Transaction service unavailable")); } else { const transactions = []; const count = Math.floor(Math.random() * 8) + 2;

             for (let i = 0; i < count; i++) {
                 transactions.push({
                     transactionId: `tx-${Date.now()}-${Math.random().toString(36).substring(2, 7)}`,
                     customerData: {
                         id: `user-${Math.floor(Math.random() * 1000)}`,
                     },
                     amount: +(Math.random() * 200 + 10).toFixed(2),
                     status: Math.random() < 0.9 ? "completed" : "pending",
                     items: Math.floor(Math.random() * 5) + 1,
                     createdAt: new Date(Date.now() - Math.floor(Math.random() * 3600000)).toISOString()
                 });
             }
             resolve({
                 data: transactions,
                 meta: {
                     total: transactions.length,
                     timeframe: timeWindow
                 }
             });
         }
     }, delay);
    

    }); }

/**

  • Fetches inventory status updates

  • Returns stock level alerts and changes

  • Fast but returns data in a completely different structure */ async function fetchInventoryAlerts(urgencyLevel = "all") { return new Promise((resolve, reject) => { const delay = 50 + Math.random() * 100; // 50-150ms setTimeout(() => { if (Math.random() < 0.1) { reject(new Error("Inventory service connection refused")); } else { // Returns XML-like string that needs parsing const alertCount = Math.floor(Math.random() * 5); let xmlResponse = &lt;inventory-alerts generated="${new Date().toISOString()}" count="${alertCount}"&gt;;

             for (let i = 0; i < alertCount; i++) {
                 const productId = Math.floor(Math.random() * 1000);
                 const currentStock = Math.floor(Math.random() * 10);
                 const threshold = 5;
                 const urgency = currentStock < 2 ? "high" : "medium";
    
                 if (urgencyLevel === "all" || urgencyLevel === urgency) {
                     xmlResponse += `
             &lt;alert type="stock" urgency="${urgency}"&gt;
               &lt;product id="${productId}" /&gt;
               &lt;current-stock&gt;${currentStock}&lt;/current-stock&gt;
               &lt;threshold&gt;${threshold}&lt;/threshold&gt;
               &lt;location warehouse="${Math.floor(Math.random() * 5) + 1}" /&gt;
             &lt;/alert&gt;
           `;
                 }
             }
    
             xmlResponse += '&lt;/inventory-alerts&gt;';
             resolve(xmlResponse);
         }
     }, delay);
    

    }); }

Task:

Create an Express.js API endpoint that:

  • Implements a GET /api/dashboard endpoint that accepts a timeWindow query parameter (e.g., "15m", "1h", "24h")
  • Fetches data from all three services concurrently
  • Handles the different response formats, error scenarios, and partial data
  • Aggregates the data into a unified dashboard response
  • Implements proper timeout handling (maximum 300ms total response time)

Sample response :

{
"dashboard": {
"timeWindow": "15m", // or whatever was requested
"summary": {
"activeUsers": 42,
"revenueTotal": 1234.56,
"conversionRate": 2.7,
"inventoryAlerts": 3
},
"details": {
"userActivity": {
// Processed user activity data
"complete": true|false,
// Additional details
},
"transactions": {
// Processed transaction data
// Additional details
},
"inventory": {
// Processed inventory data
// Additional details
}
},
"status": {
"servicesResponded": ["userActivity", "transactions", "inventory"],
"servicesFailed": [],
"responseTime": 298
}
}
}

SDE3 | Tesco | Bangalore
tesco logo
Tesco
SDE IIbangalore10.5 yearsOffer
June 13, 202440 reads

Summary

I interviewed for an SDE3 role at Tesco in Bangalore, a process that unexpectedly stretched over six months. Despite some initial scheduling hurdles and a challenging system design round, I successfully navigated the interviews and ultimately received an offer for an SDE2 position.

Full Experience

The entire interview process for Tesco stretched on for close to six months, which was quite unusual for me. It wasn't about the number of rounds, but rather the constant rescheduling; HR would book interviews only for the panel to not show up, citing busy schedules. This cycle repeated for the first two rounds, making some of the details a bit fuzzy now.

Round 1: Coding + DSA
This round involved a problem focused on merging store employee schedules. It felt very similar to the 'Merge Intervals' problem on LeetCode. There was some initial confusion regarding input types, as the problem description and inputs were given in plain text. I managed to solve it, and I recall a follow-up question specifically about mutability, as I was updating the result directly on the input list. The feedback for this round was positive.

Round 2: System Design
The challenge here was to design a train booking system, much like IRCTC. The requirements were specific but limited: I needed to implement features for searching train journeys between a source and destination, booking seats (with a strong emphasis on handling concurrency), and canceling a booking. I admit I stumbled a bit in this round; I felt overwhelmed by the time constraints and didn't approach the problem as systematically as I would have liked. Nevertheless, I persisted and managed to present an abstract design.

Round 3: Behavioural
This round covered standard behavioral questions, focusing on my strengths and weaknesses, and presented hypothetical situations designed to assess my leadership and decision-making skills. I believe I performed fairly well here.

Introductory Round with Hiring Manager
This was more of a casual interaction and introduction with the hiring manager.

Ultimately, I believe my performance in the second round, the System Design round, influenced the decision to offer me an SDE2 role instead of the SDE3 position I initially applied for. You can find compensation details here.

Interview Questions (3)

Q1
Merge Employee Schedules
Data Structures & AlgorithmsMedium

Design an algorithm to merge store employee schedules. The problem description and inputs were given in plain text. A follow-up question was asked about mutability when updating the result on the input list.

Q2
Design Train Booking System
System DesignHard

Design a train booking system, similar to IRCTC, with the following core functionalities:

  • Search train journeys between a given source and destination.
  • Book seats on a train journey, with a strong focus on handling concurrency issues.
  • Cancel an existing booking.

Q3
Behavioral Interview Questions
Behavioral

This round included questions about my professional strengths and weaknesses, as well as hypothetical scenarios designed to assess my leadership qualities and decision-making process.

Tesco - SDE 3 - Bangalore - Offer (From 5 LPA to 66LPA in 6 years)
tesco logo
Tesco
SDE 3Bangalore6 yearsOffer
May 22, 202427 reads

Summary

I successfully navigated a challenging interview process for an SDE 3 role at Tesco in Bangalore, ultimately receiving an offer. The rounds included problem-solving (DSA), system design (HLD + LLD), and a behavioral assessment.

Full Experience

After facing initial challenges in my career, I've learned that consistent motivation and smart work are key, not just past academic achievements or FAANG status. Tesco had previously rejected me, but when they reached out again, I decided to explore the opportunity, seeing it as a chance to gain more valuable interview experience. My past interview experiences with Google, Microsoft, and Amazon certainly helped streamline my preparation.

The interview process began with a standard Recruiter Screen, which involved clarifying my resume and technical skills.

The second round was a Problem Solving / DSA round. It involved a LeetCode medium problem—a variation of the merge intervals problem. The interviewer pushed for an optimal solution, alternative approaches, and demanded 'production quality' code complete with all necessary test cases.

Next was a challenging System Design round, which combined both High-Level Design (HLD) and Low-Level Design (LLD), and was led by the hiring manager. This round focused on a variation of the 'top k hitter' problem, but it went significantly deeper than solutions typically found online. There were also scenario-based questions and discussions about my existing projects. I wasn't entirely sure how I performed in this round.

After a three-week wait, I was invited for a fourth round with the head of engineering, which was purely a Behavioral round. This round focused on my projects, team management skills, and how my career experiences aligned with Tesco's values. I admit I underestimated this round and fumbled on a few questions, despite knowing the STAR method. Fortunately, I managed to recover.

Two weeks passed without any updates after the final round, leading me to believe I might not have been shortlisted, especially after the challenging system design round. However, I eventually received an email requesting government ID and other documents. This led to a salary negotiation call with the recruiter, and I received the offer within three working days.

Interview Questions (3)

Q1
Merge Intervals Variation (Production Quality Code)
Data Structures & AlgorithmsMedium

A variation of the standard Merge Intervals problem, requiring an optimal solution along with other potential approaches. The interviewer emphasized writing 'production quality' code, which meant not only solving the problem but also identifying and writing all necessary test cases.

Q2
Top K Hitter System Design (HLD + LLD)
System DesignHard

Design a system for a variation of the 'top k hitter' problem. This round required going significantly deeper than typical solutions found on the internet and covered both High-Level Design (HLD) and Low-Level Design (LLD). It also included scenario-based questions and discussions about existing projects.

Q3
Behavioral and Project Management Questions
Behavioral

Questions focused on past projects, team management experiences, and other behavioral aspects. The primary goal was to assess if my career experiences demonstrated Tesco's values. It's crucial to prepare answers using the STAR method, as underestimating this round can lead to difficulties.

Preparation Tips

My prior interview experiences with companies like Google, Microsoft, and Amazon provided a solid foundation for my preparation. Specifically for behavioral rounds, I learned the critical importance of preparing answers using the STAR method, as underestimating this round can lead to difficulties, as it did for me during the interview.

Tesco | SDE2
tesco logo
Tesco
SDE IIOngoing
March 6, 202444 reads

Summary

I interviewed for an SDE2 position at Tesco, which involved multiple rounds focusing on data structures & algorithms, system design, and managerial discussions. I was asked to solve 'Merge Intervals' and design an 'Inventory System'.

Full Experience

My interview process for the SDE2 role at Tesco consisted of four distinct rounds. The first round was dedicated to Data Structures & Algorithms, where I encountered a medium-level coding problem and was also quizzed on Java-specific questions. This was followed by a System Design round, which required me to design an Inventory System, drawing inspiration from large-scale e-commerce platforms like Amazon or Flipkart. The subsequent two rounds were with the Hiring Manager and then HR, completing the interview process.

Interview Questions (2)

Q1
Merge Intervals
Data Structures & AlgorithmsMedium

Given an array of intervals where intervals[i] = [starti, endi], merge all overlapping intervals, and return an array of the non-overlapping intervals that cover all the intervals in the input.

Q2
Design an Inventory System
System DesignHard

Design a scalable and robust inventory management system, similar to those used by large e-commerce platforms like Amazon or Flipkart. Consider key components such as stock updates, order fulfillment, multi-location support, and ensuring real-time consistency.

Have a Tesco Interview Experience to Share?

Help other candidates by sharing your interview experience. Your insights could make the difference for someone preparing for their dream job at Tesco.