Skillz Backend Engineer Role in Bangalore

Skillz Backend Engineer Role:

If you’re reading this, there’s a good chance you spend your days thinking about databases, APIs, and how to make things run faster. (No judgment—we do too.) And if you’ve ever secretly smiled when a tricky piece of code finally worked? Yeah, you’re in the right place.

What is Skillz Inc.? Company Overview

  • What we do: We make mobile gaming competitive.
  • How we do it: By giving developers tools to add tournaments, prizes, and real-money play to their games.
  • Why it matters: Because competition is fun, and we believe anyone with skill should have a shot at winning.

Backend Engineer Job Overview – Skillz Bengaluru

Backend Engineer Eligibility & Skills Required

Eligibility Criteria

CriteriaRequirement
Experience6 months – 2 years
EducationBachelor’s in Computer Science or equivalent
Work ModeIn-office 3 days a week (Bengaluru)
IndustryGaming experience preferred, not mandatory

Skills Required

Skill AreaWhat You Need
LanguagesGolang (Go) OR Java
Core CSData structures, algorithms, OOP, complexity analysis
Distributed SystemsMulti-tiered systems, caching (Redis/Memcached), relational databases
CloudAWS, Azure, or GCP
MicroservicesBuilding new services or enhancing existing ones
System DesignLow-level design (LLD) from requirements
OperationsSystem KPIs, SLAs, reliability improvements
CommunicationClear technical articulation across teams

Backend Engineer Roles and Responsibilities at Skillz

What You’ll Do Day-to-Day

🚀 Build & Scale — Create backend systems that power millions of tournaments
💻 Write Code — Ship clean, scalable code in Go or Java
📐 Design Systems — Turn ideas into precise low-level designs (LLD)
🔧 Build Microservices — Create new services and improve existing ones
🗄️ Handle Data — Work with Redis, Memcached, and relational databases
☁️ Deploy on Cloud — Use AWS, Azure, or GCP like a pro
📊 Keep Things Fast — Improve system KPIs, SLAs, and reliability
🤝 Collaborate — Work with product, frontend, and QA teams
🎙️ Share Ideas — Explain technical stuff clearly to anyone

Skillz Backend Engineer Hiring Process

Simple. Transparent. Human.

📄
Step 1

Application Review — We review your resume. If it’s a match, we reach out within 5–7 days.

📞
Step 2

Recruiter Screening — A 30-min friendly chat. We get to know you. You get to know us.

💻
Step 3

Technical Assessment — A practical coding exercise in Go or Java. No tricks. Just real problem-solving.

👥
Step 4

Technical Interviews — 2–3 rounds covering system design, distributed systems, and how you think.

🤝
Step 5

Leadership & Culture Fit — A conversation about your growth, values, and what makes you tick.

🎉
Step 6

Offer & Onboarding — Welcome to the team! We’ll help you settle in and start making impact from day one.

We move fast but respectfully. We’ll keep you updated at every stage. Questions? Just ask.

Skillz Backend Engineer Salary & Benefits

Compensation

ComponentDetails
Base SalaryCompetitive, based on experience
BonusAnnual performance bonus
EquityStock options – share in Skillz success

Perks

BenefitDetails
Health InsuranceCoverage for you and dependents
Tax SavingsFBP for fuel, internet, phone bills
RetirementNational Pension System (NPS)
Work ModeHybrid – 3 days in-office
GrowthMentorship from top tech experts

5 Mistakes to Avoid – Backend Engineer Role at Skillz

🚫 Listing languages you barely know — Show real Go or Java experience.

⚡ Ignoring scale stories — Mention Redis, Memcached, or performance wins.

💤 Applying like any other job — Tell us why Skillz excites you.

🌀 Skipping system thinking — Practice low-level design basics.

🔧 Only hyping new features — Share how you kept systems reliable.

Skillz Backend Engineer | Coding Interview Questions

⚡ Skillz Backend Engineer | Coding Interview Questions

Golang • Java • Distributed Systems • Concurrency • System Design • Real-World Problems

⏱️ 1. Rate Limiter — Token Bucket Algorithm

📖 Problem

Design a rate limiter that allows at most N requests per second per user. Implement the allowRequest(userId) method. This tests your understanding of caching, concurrency, and distributed systems.

📥 Example: Limit = 3 requests/second
📤 Output: First 3 requests return true, 4th request within same second returns false

☕ Java Code — Token Bucket

import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicLong;

public class RateLimiter {
    private final int maxRequests;
    private final long windowMs;
    private final ConcurrentHashMap<String, AtomicLong> counterMap = new ConcurrentHashMap<>();
    
    public RateLimiter(int maxRequests, long windowMs) {
        this.maxRequests = maxRequests;
        this.windowMs = windowMs;
    }
    
    public boolean allowRequest(String userId) {
        long now = System.currentTimeMillis();
        long windowKey = now / windowMs;
        String key = userId + ":" + windowKey;
        
        AtomicLong counter = counterMap.computeIfAbsent(key, k -> new AtomicLong(0));
        
        // Clean up old entries
        if (counterMap.size() > 1000) {
            counterMap.entrySet().removeIf(entry -> 
                Long.parseLong(entry.getKey().split(":")[1]) < (now / windowMs) - 2);
        }
        
        return counter.incrementAndGet() <= maxRequests;
    }
    
    public static void main(String[] args) throws InterruptedException {
        RateLimiter limiter = new RateLimiter(3, 1000);
        
        System.out.println(limiter.allowRequest("user1")); // true
        System.out.println(limiter.allowRequest("user1")); // true
        System.out.println(limiter.allowRequest("user1")); // true
        System.out.println(limiter.allowRequest("user1")); // false
        
        Thread.sleep(1000);
        System.out.println(limiter.allowRequest("user1")); // true (new window)
    }
}
✅ Output: true, true, true, false, true
🎯 Approach: Token Bucket / Sliding Window with ConcurrentHashMap. Critical for distributed systems to prevent API abuse.
🗄️ 2. Thread-Safe Cache with TTL

📖 Problem

Implement an in-memory cache that supports put(key, value, ttl) and get(key) with automatic expiry. Must be thread-safe — exactly what you'd use with Redis/Memcached.

📥 Input: put("key1", "value1", 2000), wait 1s → get("key1") returns "value1", wait another 1.5s → get("key1") returns null

☕ Java Code — Concurrent Cache

import java.util.concurrent.*;
import java.util.*;

public class TTLCache<K, V> {
    private static class CacheEntry<V> {
        V value;
        long expiryTime;
        
        CacheEntry(V value, long ttlMs) {
            this.value = value;
            this.expiryTime = System.currentTimeMillis() + ttlMs;
        }
        
        boolean isExpired() {
            return System.currentTimeMillis() > expiryTime;
        }
    }
    
    private final ConcurrentHashMap<K, CacheEntry<V>> cache = new ConcurrentHashMap<>();
    private final ScheduledExecutorService cleaner = Executors.newSingleThreadScheduledExecutor();
    
    public TTLCache() {
        cleaner.scheduleAtFixedRate(this::cleanExpired, 1, 1, TimeUnit.SECONDS);
    }
    
    public void put(K key, V value, long ttlMs) {
        cache.put(key, new CacheEntry<>(value, ttlMs));
    }
    
    public V get(K key) {
        CacheEntry<V> entry = cache.get(key);
        if (entry == null || entry.isExpired()) {
            cache.remove(key);
            return null;
        }
        return entry.value;
    }
    
    private void cleanExpired() {
        cache.entrySet().removeIf(entry -> entry.getValue().isExpired());
    }
    
    public static void main(String[] args) throws InterruptedException {
        TTLCache<String, String> cache = new TTLCache<>();
        
        cache.put("tournament", "active", 2000);
        System.out.println(cache.get("tournament")); // active
        
        Thread.sleep(2500);
        System.out.println(cache.get("tournament")); // null
    }
}
✅ Output: active, null
🎯 Approach: ConcurrentHashMap for thread-safety, ScheduledExecutor for background cleanup. Mimics Redis/Memcached behavior.
🚀 3. Golang Concurrency — Fan-Out Worker Pool

📖 Problem

Process 1000 tournament match results using a worker pool of 10 goroutines. This tests your understanding of Go concurrency, channels, and wait groups — essential for high-throughput backend services.

📥 Task: Process 1000 jobs with 10 workers, collect all results

🐹 Golang Code — Worker Pool

package main

import (
    "fmt"
    "sync"
    "time"
)

func worker(id int, jobs <-chan int, results chan<- int, wg *sync.WaitGroup) {
    defer wg.Done()
    for job := range jobs {
        // Simulate processing tournament result
        time.Sleep(10 * time.Millisecond)
        results <- job * 2 // some processing
        fmt.Printf("Worker %d processed job %d\n", id, job)
    }
}

func main() {
    const numJobs = 1000
    const numWorkers = 10
    
    jobs := make(chan int, numJobs)
    results := make(chan int, numJobs)
    
    var wg sync.WaitGroup
    
    // Start workers
    for w := 1; w <= numWorkers; w++ {
        wg.Add(1)
        go worker(w, jobs, results, &wg)
    }
    
    // Send jobs
    for j := 1; j <= numJobs; j++ {
        jobs <- j
    }
    close(jobs)
    
    // Wait for all workers to finish
    go func() {
        wg.Wait()
        close(results)
    }()
    
    // Collect results
    count := 0
    for result := range results {
        count++
        _ = result
    }
    
    fmt.Printf("Processed %d results\n", count)
}
✅ Output: Processed 1000 results
🎯 Approach: Fan-out pattern with worker pool. Critical for building scalable microservices that handle high concurrency.
🏧 4. Low-Level Design — ATM Machine (LLD)

📖 Problem

Design an ATM machine with withdraw, deposit, and balance check functionality. Focus on object-oriented design, encapsulation, and state management — exactly what you'll do when building microservices at Skillz.

📥 Scenario: User withdraws 500 from balance 2000 → remaining 1500

☕ Java Code — ATM LLD

import java.util.*;

interface ATMState {
    void insertCard();
    void ejectCard();
    void enterPin(int pin);
    void requestCash(int amount);
}

class ATM {
    private ATMState state;
    private int balance;
    private boolean cardInserted;
    private int enteredPin;
    
    public ATM(int initialBalance) {
        this.balance = initialBalance;
        this.state = new IdleState(this);
        this.cardInserted = false;
    }
    
    void setState(ATMState state) { this.state = state; }
    int getBalance() { return balance; }
    void setBalance(int balance) { this.balance = balance; }
    boolean isCardInserted() { return cardInserted; }
    void setCardInserted(boolean inserted) { this.cardInserted = inserted; }
    void setEnteredPin(int pin) { this.enteredPin = pin; }
    int getEnteredPin() { return enteredPin; }
    
    public void insertCard() { state.insertCard(); }
    public void ejectCard() { state.ejectCard(); }
    public void enterPin(int pin) { state.enterPin(pin); }
    public void requestCash(int amount) { state.requestCash(amount); }
}

class IdleState implements ATMState {
    private ATM atm;
    
    IdleState(ATM atm) { this.atm = atm; }
    
    public void insertCard() {
        System.out.println("Card inserted");
        atm.setCardInserted(true);
        atm.setState(new HasCardState(atm));
    }
    public void ejectCard() { System.out.println("No card to eject"); }
    public void enterPin(int pin) { System.out.println("Insert card first"); }
    public void requestCash(int amount) { System.out.println("Insert card first"); }
}

class HasCardState implements ATMState {
    private ATM atm;
    
    HasCardState(ATM atm) { this.atm = atm; }
    
    public void insertCard() { System.out.println("Card already inserted"); }
    public void ejectCard() {
        System.out.println("Card ejected");
        atm.setCardInserted(false);
        atm.setState(new IdleState(atm));
    }
    public void enterPin(int pin) {
        if (pin == 1234) {
            System.out.println("PIN correct");
            atm.setState(new AuthenticatedState(atm));
        } else {
            System.out.println("Wrong PIN");
            ejectCard();
        }
    }
    public void requestCash(int amount) { System.out.println("Enter PIN first"); }
}

class AuthenticatedState implements ATMState {
    private ATM atm;
    
    AuthenticatedState(ATM atm) { this.atm = atm; }
    
    public void insertCard() { System.out.println("Card already inserted"); }
    public void ejectCard() {
        System.out.println("Card ejected");
        atm.setCardInserted(false);
        atm.setState(new IdleState(atm));
    }
    public void enterPin(int pin) { System.out.println("PIN already entered"); }
    public void requestCash(int amount) {
        if (amount <= atm.getBalance()) {
            atm.setBalance(atm.getBalance() - amount);
            System.out.println("Withdrawn: " + amount + ", Remaining: " + atm.getBalance());
            ejectCard();
        } else {
            System.out.println("Insufficient balance");
            ejectCard();
        }
    }
}

public class ATMMachine {
    public static void main(String[] args) {
        ATM atm = new ATM(2000);
        atm.insertCard();
        atm.enterPin(1234);
        atm.requestCash(500);
    }
}
✅ Output: Card inserted → PIN correct → Withdrawn: 500, Remaining: 1500 → Card ejected
🎯 Approach: State Design Pattern with clear separation of concerns. Essential for translating requirements into low-level designs.
📊 5. Distributed Counter — Tournament Score Aggregator

📖 Problem

Design a distributed counter that safely increments across multiple threads/nodes. At Skillz, you'll handle millions of concurrent tournament score updates — this tests your understanding of atomic operations and consistency.

📥 Scenario: 1000 concurrent increments on same counter

☕ Java Code — Atomic Counter

import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.*;
import java.util.*;

public class DistributedCounter {
    private final AtomicLong counter = new AtomicLong(0);
    
    public long increment() {
        return counter.incrementAndGet();
    }
    
    public long get() {
        return counter.get();
    }
    
    public static void main(String[] args) throws InterruptedException {
        DistributedCounter counter = new DistributedCounter();
        int numThreads = 100;
        int incrementsPerThread = 1000;
        
        ExecutorService executor = Executors.newFixedThreadPool(numThreads);
        CountDownLatch latch = new CountDownLatch(numThreads);
        
        for (int i = 0; i < numThreads; i++) {
            executor.submit(() -> {
                for (int j = 0; j < incrementsPerThread; j++) {
                    counter.increment();
                }
                latch.countDown();
            });
        }
        
        latch.await();
        executor.shutdown();
        
        System.out.println("Final counter: " + counter.get());
        System.out.println("Expected: " + (numThreads * incrementsPerThread));
    }
}
✅ Output: Final counter: 100000, Expected: 100000
🎯 Approach: AtomicLong for lock-free thread-safety. Essential for distributed systems where you need consistent counts (tournament entries, scores, etc.).

Backend Engineer Role Skillz - FAQs

  • Need gaming experience?
    No. Backend skills matter more.
  • Remote or in-office?
    Hybrid – 3 days a week in Bengaluru.
  • Know Java but not Go?
    Yes, apply. Openness to learn Go is key.
  • What's in the technical interview?
    LLD, system design, data structures, and coding in Go/Java.
  • Response time?
    5–7 business days after applying.

How To Apply for Skillz Backend Engineer

📮

Ready to Level Up Your Career?

Join Skillz Bengaluru and build the future of mobile eSports

1 Click the Apply Now button below
2 Fill in your details and upload your resume
3 Our team will reach out within 5–7 business days
Apply Now →

📍 Location: Skillz, Table Space Towers, Krishnarajapuram, Bengaluru

💡

Final Pro Tip

Don't just tell us what you've done — show us how you think. When you write your application or walk into the interview, share the *why* behind your decisions. That's what sets great engineers apart.

Other Opportunities

🚀 Other Active Opportunities

GrabHack 2.0: AI Hackathon

Grab • 2 years Experience

Apply

Java Associate 2026

Accenture • 0-2 years

Apply

Scroll to Top