If you are preparing for the Swiggy Business Analyst role, you need a solid grip on SQL, delivery operations metrics, and structured problem-solving. This guide covers the most commonly asked Swiggy Business Analyst interview questions from 2024–2026 interview cycles — complete with model answers, interviewer insights, and follow-up questions you should be ready to handle. Swiggy’s BA round tests your ability to translate messy operational data into actionable business decisions, especially around food delivery, Instamart quick-commerce, and restaurant partner health.
Business Metrics
Delivery Analytics
Tableau
Excel / Python
Round 1 — SQL & Data Analysis (40 mins)
| Questions | 5 |
| Duration | 40 minutes |
| Difficulty | Easy-Medium to Medium |
| Key Topics | PercentilesWindow FunctionsConditional AggregationTime CalculationsCohort Analysis |
The operations team wants to understand delivery time distribution by city. Calculate the 50th, 75th, 90th, and 95th percentile delivery time (minutes from order placed to delivered) by city. Identify cities where the p90 delivery time exceeds 45 minutes.
Table:
- deliveries(order_id, restaurant_id, rider_id, order_placed_at, picked_up_at, delivered_at, city, order_value)
DATEDIFF or TIMESTAMPDIFF between order_placed_at and delivered_at? Candidates often confuse minutes vs seconds here. They also test whether you know PERCENTILE_CONT (standard SQL) vs APPROX_PERCENTILE (some Swiggy dialects use Presto/Spark SQL). Filtering out NULL delivered_at for cancelled orders is a common miss.WITH delivery_times AS (
SELECT
city,
order_id,
TIMESTAMPDIFF(MINUTE, order_placed_at, delivered_at) AS delivery_minutes
FROM deliveries
WHERE delivered_at IS NOT NULL
),
city_percentiles AS (
SELECT
city,
PERCENTILE_CONT(0.50) WITHIN GROUP (ORDER BY delivery_minutes) AS p50,
PERCENTILE_CONT(0.75) WITHIN GROUP (ORDER BY delivery_minutes) AS p75,
PERCENTILE_CONT(0.90) WITHIN GROUP (ORDER BY delivery_minutes) AS p90,
PERCENTILE_CONT(0.95) WITHIN GROUP (ORDER BY delivery_minutes) AS p95
FROM delivery_times
GROUP BY city
)
SELECT
city,
ROUND(p50, 1) AS p50_minutes,
ROUND(p75, 1) AS p75_minutes,
ROUND(p90, 1) AS p90_minutes,
ROUND(p95, 1) AS p95_minutes,
CASE WHEN p90 > 45 THEN 'FLAG: p90 > 45 min' ELSE 'OK' END AS sla_flag
FROM city_percentiles
ORDER BY p90 DESC;
PERCENTILE_CONT interpolates between values to give an exact percentile (vs PERCENTILE_DISC which returns an actual value from the dataset). Always filter WHERE delivered_at IS NOT NULL to exclude cancelled or in-progress orders — including them would artificially inflate delivery times. The CASE WHEN p90 > 45 flag at the end is a simple but effective way to surface actionable cities without post-processing in Python.- How would you compute delivery time percentiles broken down by restaurant_id within each city?
- If Swiggy’s SLA target changes from 45 min to 40 min for metro cities, how do you parameterise this query?
- What does a large gap between p75 and p90 tell you about the delivery time distribution?
The restaurant partnerships team wants to identify underperforming restaurant partners before churn. Calculate for each restaurant: acceptance rate, cancellation rate, and average weekly orders. Flag restaurants where acceptance rate < 80% OR (cancellation rate > 10% AND weekly orders > 50).
Table:
- orders(order_id, restaurant_id, status, order_date) — status values: placed, accepted, cancelled_by_restaurant, delivered, returned
accepted / placed, not accepted / all statuses. Many candidates count delivered orders as accepted, missing that a placed order that goes directly to cancelled was never accepted. The compound flag condition (OR + AND precedence) is also a common source of bugs — interviewers watch for missing parentheses.WITH restaurant_stats AS (
SELECT
restaurant_id,
COUNT(order_id) AS total_orders,
COUNT(CASE WHEN status = 'accepted' THEN 1 END) AS accepted_count,
COUNT(CASE WHEN status = 'cancelled_by_restaurant' THEN 1 END) AS cancelled_count,
COUNT(DISTINCT DATE_FORMAT(order_date, '%Y-%u')) AS total_weeks
FROM orders
GROUP BY restaurant_id
)
SELECT
restaurant_id,
total_orders,
ROUND(100.0 * accepted_count / NULLIF(total_orders, 0), 1) AS acceptance_rate_pct,
ROUND(100.0 * cancelled_count / NULLIF(total_orders, 0), 1) AS cancellation_rate_pct,
ROUND(1.0 * total_orders / NULLIF(total_weeks, 0), 1) AS avg_weekly_orders,
CASE
WHEN (100.0 * accepted_count / NULLIF(total_orders, 0)) < 80
OR (
(100.0 * cancelled_count / NULLIF(total_orders, 0)) > 10
AND (1.0 * total_orders / NULLIF(total_weeks, 0)) > 50
)
THEN 'FLAG'
ELSE 'OK'
END AS health_flag
FROM restaurant_stats
ORDER BY health_flag DESC, cancellation_rate_pct DESC;
DATE_FORMAT(order_date, '%Y-%u') to count distinct ISO weeks, then divide total orders by week count for average weekly orders. The compound flag requires explicit parentheses around the AND clause to enforce correct operator precedence — without them, SQL evaluates OR before AND by default, which inverts the logic. Always use NULLIF to guard against division by zero for new restaurants.- How would you track week-over-week change in acceptance rate to catch restaurants trending down?
- What action would you recommend to the partnerships team for a flagged restaurant with high cancellation but very high order volume?
- How would you build an automated alert if a restaurant’s cancellation rate crosses 10% within a 7-day rolling window?
Top Resources to Crack Swiggy BA Interview
Affordable, practical, and interview-focused
- 2,200+ questions · 23 topics
- SQL, Python, case study frameworks
- Covers food-tech and product company patterns
- 220+ questions · SQL advanced, data models, DBMS
- Window functions, CTEs, complex joins
- Operations and e-commerce SQL patterns
The growth team wants a multi-dimensional view of order cancellations. Using the cancellations table, find: (a) top 5 cancellation reasons by volume, (b) time-to-cancel distribution in buckets, (c) restaurants with the highest user-initiated cancellation rate.
Table:
- orders(order_id, user_id, restaurant_id, cancel_reason, cancel_by, cancelled_at, order_placed_at)
-- (a) Top 5 cancellation reasons by volume
SELECT
cancel_reason,
COUNT(order_id) AS cancellations,
ROUND(100.0 * COUNT(order_id) / SUM(COUNT(order_id)) OVER (), 1) AS pct_of_total
FROM orders
WHERE cancelled_at IS NOT NULL
GROUP BY cancel_reason
ORDER BY cancellations DESC
LIMIT 5;
-- (b) Time-to-cancel distribution (minutes buckets)
SELECT
CASE
WHEN TIMESTAMPDIFF(MINUTE, order_placed_at, cancelled_at) <= 2 THEN '0-2 min'
WHEN TIMESTAMPDIFF(MINUTE, order_placed_at, cancelled_at) <= 5 THEN '3-5 min'
WHEN TIMESTAMPDIFF(MINUTE, order_placed_at, cancelled_at) <= 10 THEN '6-10 min'
WHEN TIMESTAMPDIFF(MINUTE, order_placed_at, cancelled_at) <= 20 THEN '11-20 min'
ELSE '20+ min'
END AS cancel_bucket,
COUNT(order_id) AS cancellations
FROM orders
WHERE cancelled_at IS NOT NULL
AND cancel_by = 'user'
GROUP BY cancel_bucket
ORDER BY MIN(TIMESTAMPDIFF(MINUTE, order_placed_at, cancelled_at));
-- (c) Restaurants with highest user-initiated cancellation rate
SELECT
restaurant_id,
COUNT(order_id) AS total_orders,
COUNT(CASE WHEN cancel_by = 'user' THEN 1 END) AS user_cancels,
ROUND(100.0 * COUNT(CASE WHEN cancel_by = 'user' THEN 1 END)
/ NULLIF(COUNT(order_id), 0), 1) AS user_cancel_rate_pct
FROM orders
GROUP BY restaurant_id
HAVING COUNT(order_id) >= 50
ORDER BY user_cancel_rate_pct DESC
LIMIT 10;
SUM(COUNT()) OVER () — a window function on an aggregated column — to compute percentage share without a subquery. Part (b) classifies time-to-cancel into business-meaningful buckets; cancellations in the first 2 minutes are almost always due to accidental orders or price shock, while 20+ minute cancellations often indicate late delivery. Part (c) uses a HAVING COUNT >= 50 guard to avoid restaurants with tiny order volumes skewing the rate.- How would you distinguish between cancellations due to restaurant delay vs user change-of-mind?
- If “delivery too slow” is the top reason, what data would you need to validate that the restaurant is actually causing the delay?
- How would you build a predictive model to flag orders likely to be cancelled before they are?
The marketing team wants to understand monthly revenue contribution from new vs returning users and how promo discounts differ between segments. A user is “new” in a given month if it’s their first-ever order on the platform.
Table:
- orders(order_id, user_id, order_date, order_value, promo_discount)
WITH first_order AS (
SELECT
user_id,
MIN(order_date) AS first_order_date
FROM orders
GROUP BY user_id
),
orders_with_segment AS (
SELECT
o.order_id,
o.user_id,
DATE_FORMAT(o.order_date, '%Y-%m') AS order_month,
o.order_value,
o.promo_discount,
CASE
WHEN DATE_FORMAT(o.order_date, '%Y-%m')
= DATE_FORMAT(f.first_order_date, '%Y-%m')
THEN 'New User'
ELSE 'Returning User'
END AS user_segment
FROM orders o
JOIN first_order f ON o.user_id = f.user_id
)
SELECT
order_month,
user_segment,
COUNT(DISTINCT user_id) AS unique_users,
COUNT(order_id) AS total_orders,
ROUND(SUM(order_value), 0) AS total_revenue,
ROUND(AVG(order_value), 1) AS avg_order_value,
ROUND(AVG(promo_discount), 1) AS avg_promo_discount
FROM orders_with_segment
GROUP BY order_month, user_segment
ORDER BY order_month, user_segment;
MIN(order_date) and comparing year-month, not just month. Interviewers look for this nuance: candidates who just compare order_month = first_order_month without the year component will incorrectly classify a March 2025 first-time user as “new” again in March 2026.- How would you compute 30-day repeat order rate for new users acquired in each month (cohort retention)?
- If new users get higher discounts, how do you determine whether the CAC is justified by LTV?
- How would you flag users who are “reactivated” after 90+ days of inactivity as a third segment?
The fleet operations team wants a daily rider efficiency score. Build a composite score using: deliveries per hour worked, on-time rate (delivery time minus pickup time < 30 minutes), and average distance per delivery. Rank riders within each city.
Tables:
- deliveries(delivery_id, rider_id, pickup_time, delivery_time, km_distance, tip_amount)
- riders(rider_id, city, joined_date)
WITH daily_rider_stats AS (
SELECT
d.rider_id,
r.city,
DATE(d.pickup_time) AS work_date,
COUNT(d.delivery_id) AS total_deliveries,
TIMESTAMPDIFF(MINUTE, MIN(d.pickup_time), MAX(d.delivery_time))
/ 60.0 AS hours_worked,
AVG(CASE
WHEN TIMESTAMPDIFF(MINUTE, d.pickup_time, d.delivery_time) < 30 THEN 1.0
ELSE 0.0
END) AS on_time_rate,
AVG(d.km_distance) AS avg_km_per_delivery
FROM deliveries d
JOIN riders r ON d.rider_id = r.rider_id
GROUP BY d.rider_id, r.city, DATE(d.pickup_time)
),
rider_scores AS (
SELECT
rider_id,
city,
work_date,
total_deliveries,
ROUND(total_deliveries / NULLIF(hours_worked, 0), 2) AS deliveries_per_hour,
ROUND(on_time_rate * 100, 1) AS on_time_pct,
ROUND(avg_km_per_delivery, 2) AS avg_km,
-- Composite score: 40% deliveries/hr + 40% on-time + 20% distance efficiency
ROUND(
0.40 * LEAST(total_deliveries / NULLIF(hours_worked, 0) / 5.0, 1.0)
+ 0.40 * on_time_rate
+ 0.20 * (1.0 - LEAST(avg_km_per_delivery / 10.0, 1.0)),
3) AS efficiency_score
FROM daily_rider_stats
)
SELECT
rider_id,
city,
work_date,
deliveries_per_hour,
on_time_pct,
avg_km,
efficiency_score,
RANK() OVER (PARTITION BY city, work_date ORDER BY efficiency_score DESC) AS city_rank
FROM rider_scores
ORDER BY city, work_date, city_rank;
LEAST(..., 1.0) prevents outlier riders from inflating the composite. The distance component is inverted (shorter average distance = more efficient, as riders cover more orders per km) — make sure to explain this business logic to the interviewer.- How would you adjust the score to account for rain days when on-time rates structurally drop?
- How would you validate that this composite score actually correlates with rider satisfaction or customer rating?
- What additional data would you request to make this score more robust?
Round 2 — Business Metrics & Analysis (30 mins)
| Questions | 3 |
| Duration | 30 minutes |
| Difficulty | Medium |
| Key Topics | KPI DefinitionUnit EconomicsDark StoresPromotion ROIContribution Margin |
Instamart is Swiggy’s quick-commerce arm targeting 10-minute grocery delivery. Define 8 KPIs you would track for Instamart. For each, give the metric definition, how to calculate it from raw data, a healthy benchmark, and what action to take if it goes off track.
| KPI | Definition | Calculation | Healthy Benchmark | Action if Off Track |
|---|---|---|---|---|
| Promise Time Adherence | % orders delivered within promised window (10 min) | COUNT(delivered_at <= promised_at) / COUNT(*) | > 85% | Audit dark store picker speed and rider assignment lag |
| Order Fill Rate | % of ordered SKUs that were available and dispatched | SUM(dispatched_qty) / SUM(ordered_qty) | > 95% | Improve demand forecasting, increase safety stock for top-20 SKUs |
| Dark Store Utilisation | Actual orders / max order capacity per hour | COUNT(orders_per_hour) / store_max_capacity | 60–80% | Run flash promotions in low-utilisation windows; hire riders for high-utilisation slots |
| Basket Size | Average GMV per order | SUM(order_value) / COUNT(orders) | ₹350–₹500 | Introduce bundle deals, minimum-order promotions, or personalised cross-sell |
| Repeat Order Rate (30-day) | % of month-1 users who order again within 30 days | Cohort repeat users / cohort acquired users | > 40% | Deploy re-engagement push notifications, loyalty credits |
| Shrinkage Rate | % inventory lost to damage, expiry, or theft | Lost units / total received units | < 2% | FIFO enforcement, expiry alert system, CCTV audit at dark store |
| Customer Complaint Rate | Complaints per 100 orders | COUNT(complaints) / COUNT(orders) × 100 | < 1.5 | Root-cause by complaint type; wrong item = picker error; damage = packaging audit |
| Contribution Margin per Order | Revenue minus variable costs (COGS, rider pay, packaging, promo) | (Revenue − COGS − rider cost − packaging − discount) / orders | > ₹20/order | Reduce rider idle time, renegotiate supplier COGS, optimise promo targeting |
A Swiggy Instamart dark store in Koramangala, Bangalore has 1,200 orders/day, 94% on-time delivery, but a net margin of -18%. Walk through a cost structure analysis and identify 3 levers to improve margins without hurting delivery SLA.
Step 1: Cost Structure Analysis
For a dark store doing 1,200 orders/day at an assumed average basket of ₹380 → GMV = ~₹4.56L/day. At -18% net margin, the store loses ~₹82K/day. Typical cost buckets for Instamart:
| Cost Category | Typical % of GMV | Key Driver |
|---|---|---|
| COGS (product cost) | 55–60% | Supplier prices, shrinkage, wastage |
| Rider/delivery cost | 15–20% | Riders per order, idle time, surge pay |
| Dark store rent + ops | 8–12% | Fixed cost spread over order volume |
| Packaging | 2–3% | Bag count, insulation material |
| Promotions/discounts | 5–8% | Coupon burn, free delivery offers |
| Technology + overheads | 3–5% | Allocated HQ costs |
Step 2: 3 Margin Levers (without hurting SLA)
Lever 1 — Shrinkage & Wastage Reduction (targets COGS)
Implement AI-based demand forecasting for perishables. For a store doing 1,200 orders/day, even reducing fresh-produce wastage from 4% to 2% can reclaim 2–3% of GMV in recovered inventory cost. Action: daily sell-through reports by SKU, markdown pricing for near-expiry items, FIFO discipline in picker routing.
Lever 2 — Rider Idle Time Optimisation (targets delivery cost)
If riders average 4 deliveries/hour but capacity allows 5, you are losing 20% efficiency. Batching orders from the same micro-zone (2 orders per trip where distance allows under 500m) can increase deliveries/rider/hour without breaching the 10-min SLA for the second order. Action: analyse order heat maps by 15-min slots; deploy surge-zone rider pre-positioning 10 min before peak.
Lever 3 — Promo Targeting Precision (targets discount cost)
Currently promotions likely apply platform-wide. If 35% of orders come from repeat users who would have ordered anyway, blanket discounts are wasted. Action: segment users by order frequency; apply discounts only to users with < 2 orders in the last 30 days. This alone can cut promotional GMV burn by 30–40% while maintaining volume.
- How would you prioritise these three levers — which would you implement first and why?
- If the store has a 94% on-time rate but p95 delivery time is 18 min (vs 10-min promise), what does that tell you and how do you fix it?
- At what order volume does a dark store become margin-positive, given fixed costs of ₹1.2L/day?
During peak hours (7–9 PM), Swiggy offers a 20% discount and observes a 35% volume spike. Define contribution margin for this promotion. At what price elasticity of demand does this promotion become ROI-positive?
Setup (assume pre-promotion baseline):
Let average order value (AOV) = ₹400, variable cost per order = ₹320 (80% of AOV), so baseline contribution margin = ₹80/order (20% CM%). Baseline orders per hour = 1,000.
With 20% discount and 35% volume spike:
| Metric | Baseline | With Promotion |
|---|---|---|
| Average order value | ₹400 | ₹320 (−20%) |
| Variable cost/order | ₹320 | ₹320 (unchanged) |
| Contribution margin/order | ₹80 | ₹0 (320 − 320) |
| Order volume (per hour) | 1,000 | 1,350 (+35%) |
| Total contribution | ₹80,000 | ₹0 |
At 20% CM and a 20% discount, the discount exactly wipes out contribution margin. The promotion is ROI-negative unless the variable cost per order is below ₹320 (i.e., CM% > 20%).
Break-Even Elasticity Calculation:
Price Elasticity of Demand (PED) = % change in quantity / % change in price.
For the promotion to be ROI-neutral: revenue contribution must equal baseline. Let new AOV = 0.8 × ₹400 = ₹320. For CM to remain at ₹80: we need revenue − variable cost = ₹80 → ₹320 − VC = ₹80 → VC must fall to ₹240. That requires volume-driven cost reduction (e.g., fixed cost dilution).
Alternatively, at a 15% CM margin (variable cost = ₹340), the discount leaves CM = −₹20/order. Volume must increase by: Δ orders × (−₹20) + 1,000 × ₹60 (old CM at 15%) must be > 0 after discount. Break-even elasticity = 1.5 (for every 1% price drop, need 1.5% volume increase). The observed 35%/20% = 1.75 elasticity — barely ROI-positive at 15% baseline CM.
Round 3 — Case Study (20 mins)
| Questions | 2 |
| Duration | 20 minutes |
| Difficulty | Medium to Easy-Medium |
| Key Topics | Root Cause AnalysisFunnel AnalysisHypothesis TreeTier 2 Operations |
Swiggy’s average delivery time in Tier 2 cities is 52 minutes vs 34 minutes in Tier 1. As a BA, how would you systematically analyse the gap and recommend specific interventions? Structure your answer as a root cause tree.
Step 1 — Decompose Delivery Time into Segments
Total delivery time = Order accept lag + Food prep time + Rider pickup wait + Transit time + Last-mile time.
The 18-minute gap could live in any segment. Before recommending solutions, I would pull average time for each segment in Tier 1 vs Tier 2 to isolate where the delta is largest.
Step 2 — Data to Pull First
Before recommending any intervention, I would segment the 18-minute gap across the five delivery sub-stages. If 12 of the 18 minutes are in transit (rider to customer), it’s a geography/address problem. If 10 minutes are in order-accept lag, it’s a restaurant onboarding / POS problem. The segment with the largest delta gets intervention priority.
Step 3 — Recommended Interventions by Root Cause
- Rider density: Introduce geo-clustering incentives — riders who stay within a 2-km zone of popular restaurants during peak hours earn a zone bonus. Pilot in 3 Tier 2 cities and measure average assignment time before/after.
- Address quality: Mandate Google Maps Plus Codes on checkout in Tier 2. Allow customers to pin their exact location on a map. Show riders a pre-validated landmark instead of raw address text. This alone can save 3–5 minutes on last-mile.
- Restaurant prep time: Set prep-time SLAs per restaurant category (fast food < 8 min, casual dining < 15 min). Monitor via POS accept timestamp vs food-ready timestamp. Restaurants exceeding SLA for > 20% of orders get a prep-time coaching call from the city operations team.
- How would you measure the success of each intervention — what’s your primary metric and what’s your holdout?
- If after 30 days the delivery time improves by only 5 minutes, how do you decide whether to scale or abandon the intervention?
- What Tier 2 city would you pilot first and why?
The restaurant onboarding funnel from signup to first order is: Signup → Document Verification → Menu Upload → Training → Go Live → First Order. Only 45% of restaurants that sign up complete their first order. Identify where the biggest drop-offs likely are and propose 2 interventions per stage.
| Stage | Estimated Drop % | Likely Cause | Intervention 1 | Intervention 2 |
|---|---|---|---|---|
| Signup → Doc Verification | ~10% | Incomplete documents (FSSAI, PAN, bank details); restaurant owner unsure what to upload | In-app document checklist with sample images for each required doc type | Dedicated onboarding WhatsApp bot that reminds and guides within 24 hours of signup |
| Doc Verification → Menu Upload | ~20% | Verification takes 3–5 days; restaurants lose interest or open on competitor; menu upload UX is complex | Reduce verification TAT to 24 hours using automated OCR for common documents + human review only for exceptions | Provide a menu template (CSV or photo-based) that the Swiggy team uploads on behalf of the restaurant for first 30 days |
| Menu Upload → Training | ~10% | Training scheduling friction; restaurant staff unavailable during Swiggy’s fixed training slots | Replace mandatory in-person training with a 20-min self-serve video module accessible on any device | Assign a city partner manager to proactively call and schedule training within 48 hours of menu upload |
| Training → Go Live | ~8% | Technical issues with POS tablet setup; restaurant goes live but no orders arrive, causing discouragement | Guarantee 3 test orders from Swiggy QA team on go-live day to ensure smooth operations | Pre-go-live checklist verified by city ops: POS connected, menu photos uploaded, preparation time set correctly |
| Go Live → First Real Order | ~7% | Restaurant is live but not discoverable — no reviews, low ranking in search algorithm | New restaurant boost: auto-feature in top 10 listings in their area for first 14 days | Introductory discount (e.g., 10% off first 50 orders, funded by Swiggy) to drive initial order volume and reviews |
- How would you measure funnel conversion — what SQL query would you write to track stage-by-stage conversion rates?
- If a restaurant completes onboarding but gets zero orders in week 1, what would you do to prevent churn?
- How would you A/B test the “menu upload as a service” intervention?
4-Week Study Plan for Swiggy Business Analyst Interview
The Swiggy BA interview rewards candidates who can connect data to operational decisions quickly. Use this plan to build both SQL fluency and business intuition in parallel.
Build your foundation
SQL window functions, CTEs, conditional aggregation. Case study frameworks (MECE, funnel analysis, root cause trees). Read The Data Monk’s interview pattern posts for food-tech companies to understand what Swiggy tests.
2200 Most Asked Analytics Interview Questions
Cover the SQL section, Python section, and all case study chapters. Focus on delivery and e-commerce scenarios. End of Week 2: First mock interview →
Ace Any SQL Interview ebook
Work through all 220 questions — no shortcuts. Focus on time-series queries, percentile calculations, and composite scoring. Link: Ace Any SQL Interview. End of Week 3: Second mock interview →
Revise + timed practice
Redo first 5 chapters of the 2200 ebook. Practice 2 business metric case studies per day using food-tech scenarios. Run 15-min timed SQL sessions. End of Week 4: Final mock interview →