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