← Mithril Interview Insights

Mithril·Software Engineer·Onsite - System Design / Architecture·Senior

Senior
Jun 2026

Summary

System design round at Mithril for a software engineer role, focused entirely on designing a GPU resource allocation and job management service across a hybrid cloud setup. Pretty intense scope for a single session.

Questions Asked (7)

Q1

Design a service that allocates and manages GPU resources for ML training jobs across a hybrid cloud environment, where some GPUs are on-premises and some are in a public cloud.

System DesignTechnical Trade-offs
Author's notes

This was a lot to unpack.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Start by clarifying requirements and constraints, then design a high-level architecture that abstracts GPU resources across on-prem and cloud. Focus on the scheduler, resource management, and job lifecycle, and discuss trade-offs in placement, data movement, and cost.

Pro tip: Emphasize that the scheduler should be pluggable and policy-driven, allowing different strategies (e.g., cost-optimized, latency-optimized) without major refactoring. Also, mention that you'd start with a simple heuristic and iterate based on metrics.

1. Clarify Requirements

Ask about scale, job types, latency requirements, data locality, security, and budget constraints. Understand the mix of on-prem and cloud GPUs and any compliance needs.

2. High-Level Architecture

Outline components: a global scheduler, resource managers for each environment, a job queue, and a monitoring system. Describe how they interact via APIs.

3. Scheduling and Placement

Explain how jobs are matched to GPUs based on policies (e.g., cost, data locality, availability). Discuss preemption, gang scheduling, and handling failures.

4. Data and Network Considerations

Address data transfer between on-prem and cloud, caching, and network latency. Mention techniques like data staging and checkpointing.

5. Trade-offs and Scaling

Discuss trade-offs: cost vs. performance, complexity vs. flexibility. Explain how the system scales and handles bursts.

Key Points to Mention

  • Resource abstraction and unified API for heterogeneous GPUs
  • Scheduling policies: bin packing, spread, affinity/anti-affinity, cost-aware
  • Data locality and movement strategies (e.g., pre-staging, streaming)
  • Fault tolerance: checkpointing, retries, and job migration
  • Security and compliance: network isolation, encryption, access control
  • Monitoring and autoscaling: metrics, alerts, and dynamic resource provisioning

AI-generated suggestions, not part of the candidate's original notes. May be inaccurate — verify before relying on them.

Q2

What APIs would you expose for this system? Walk through submitting a job, checking its status, listing jobs, and canceling a job.

API & IntegrationsSystem Design
Author's notes

Went through the four endpoints pretty quickly.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Start by clarifying the system's requirements and constraints, then propose a RESTful API design with clear resource-oriented endpoints. Walk through each operation (submit, status, list, cancel) with HTTP methods, paths, request/response schemas, and status codes, while discussing trade-offs and scalability considerations.

Pro tip: Demonstrate maturity by discussing idempotency for job submission (e.g., using client-provided idempotency keys) and asynchronous processing patterns, which are critical for reliable job systems.

1. Clarify Requirements and Assumptions

Ask about expected scale, authentication, job types, and whether the API is public or internal. State assumptions to guide your design.

2. Define Resource Model and Endpoints

Identify the primary resource (e.g., jobs) and design RESTful endpoints for each operation: POST /jobs, GET /jobs/{id}, GET /jobs, DELETE /jobs/{id}.

3. Specify Request/Response Details

For each endpoint, describe HTTP method, path, headers, request body, response body, and status codes. Include examples for clarity.

4. Address Edge Cases and Non-Functional Requirements

Discuss idempotency, pagination, filtering, rate limiting, error handling, and asynchronous job processing. Mention how to handle cancellation of running jobs.

5. Summarize and Offer Extensions

Recap the API design and suggest possible extensions like webhooks, batch operations, or versioning, showing forward-thinking.

Key Points to Mention

  • Use RESTful conventions: POST for creation, GET for retrieval, DELETE for cancellation.
  • Include idempotency keys for job submission to prevent duplicate jobs.
  • Return appropriate HTTP status codes (202 Accepted for async submission, 200 OK for status, 204 No Content for cancellation).
  • Implement pagination for listing jobs (e.g., limit/offset or cursor-based).
  • Design for asynchronous processing: job submission returns immediately with a job ID and status URL.
  • Consider authentication, authorization, and rate limiting for production readiness.

AI-generated suggestions, not part of the candidate's original notes. May be inaccurate — verify before relying on them.

Q3

How would you model the data for jobs, users, and resource allocations in this system?

Data ModelingSystem Design
Author's notes

Talked through a jobs table with status, resource spec, placement info, and timestamps.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Start by clarifying the core entities and their relationships, then propose a schema that balances normalization for integrity with denormalization for query performance. Discuss how you would handle allocation logic, including constraints and concurrency, and consider scalability and access patterns.

Pro tip: Mention that you would first identify the most frequent queries and design indexes accordingly, as data modeling should be driven by access patterns, not just entity relationships.

1. Identify Entities and Relationships

Define the main entities: users, jobs, and resource allocations. Determine cardinality (e.g., one job has many allocations, one user can have many allocations) and any hierarchical or many-to-many relationships.

2. Design Core Tables

Propose tables for users, jobs, and allocations with primary keys, foreign keys, and essential attributes. For allocations, include fields like user_id, job_id, resource_type, quantity, start_time, end_time, and status.

3. Handle Allocation Logic and Constraints

Discuss how to enforce constraints such as preventing double-booking of resources, ensuring allocations don't exceed capacity, and handling time-based validity. Mention using database constraints or application-level checks.

4. Optimize for Access Patterns

Identify common queries (e.g., 'get all allocations for a user', 'find available resources for a job') and propose indexes, materialized views, or denormalization to optimize performance.

5. Consider Scalability and Evolution

Address how the model would scale (e.g., sharding by user_id or job_id) and how to handle schema changes, soft deletes, and audit trails.

Key Points to Mention

  • Normalization vs. denormalization trade-offs for read-heavy vs. write-heavy workloads
  • Use of foreign keys and referential integrity to maintain consistency
  • Indexing strategies on foreign keys and frequently filtered columns (e.g., status, timestamps)
  • Handling concurrency and race conditions in resource allocation (e.g., using transactions or optimistic locking)
  • Time-based allocation modeling (e.g., start/end timestamps, validity periods)
  • Scalability considerations such as partitioning or sharding for large datasets

AI-generated suggestions, not part of the candidate's original notes. May be inaccurate — verify before relying on them.

Q4

How would you handle failures, both at the node level and at the cloud provider API level, to keep jobs running reliably?

System DesignTechnical Trade-offs
Author's notes

Node failure was easier to reason about: heartbeat from the worker, timeout triggers a reschedule.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Structure your answer by separating node-level and cloud API-level failures, then explain how you'd detect, mitigate, and recover from each. Emphasize idempotency, retries with backoff, and graceful degradation to keep jobs running reliably.

Pro tip: Mention that you'd design for failure by assuming nodes and APIs will fail, and that you'd use circuit breakers and dead-letter queues to prevent cascading failures. Also highlight the importance of observability and chaos testing to validate resilience.

1. Classify failure types

Distinguish between node-level failures (e.g., crashes, resource exhaustion) and cloud provider API failures (e.g., throttling, timeouts, service outages).

2. Design for idempotency and retries

Ensure job operations are idempotent so retries don't cause duplicate work. Implement retry logic with exponential backoff and jitter for transient API errors.

3. Implement isolation and fallbacks

Use bulkheads to isolate failures, circuit breakers to stop calling failing APIs, and fallback mechanisms (e.g., cached data, alternate regions) to maintain progress.

4. Monitor and alert

Set up comprehensive monitoring for node health and API error rates, with alerts to detect and respond to failures quickly.

5. Test and iterate

Regularly test failure scenarios via chaos engineering and game days, and refine strategies based on post-mortems and metrics.

Key Points to Mention

  • Idempotency of job operations to allow safe retries
  • Exponential backoff with jitter for API retries
  • Circuit breakers to prevent cascading failures
  • Dead-letter queues for failed jobs and manual intervention
  • Health checks and auto-healing for node failures
  • Observability: logging, metrics, and tracing for both nodes and API calls

AI-generated suggestions, not part of the candidate's original notes. May be inaccurate — verify before relying on them.

Q5

How would you ensure fairness across tenants and enforce per-user or per-team GPU quotas?

System DesignAdaptability & Ambiguity
Author's notes

Said quota enforcement at submission time with a soft check, then a hard check at scheduling time to handle race conditions.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Start by clarifying the requirements: what does 'fairness' mean here (equal share, weighted by priority, or max-min fairness)? Then outline a multi-layered approach: admission control, scheduling, and enforcement. Emphasize that quotas must be enforced at multiple levels (tenant, team, user) with observability and graceful degradation.

Pro tip: Mention that fairness is not just about quotas but also about preventing starvation and ensuring preemption or borrowing policies. Show you understand the trade-offs between strict isolation and utilization.

1. Clarify requirements and definitions

Ask questions to understand what fairness means in this context: equal access, weighted by team priority, or max-min fairness? Also clarify the scope: per-user, per-team, per-tenant, and how quotas are set (static or dynamic).

2. Design a hierarchical quota model

Propose a tree structure: tenant -> team -> user, with quotas at each level. Use a token bucket or leaky bucket for rate limiting, and consider borrowing unused capacity from parent or siblings.

3. Implement admission control and scheduling

At request time, check if the user/team/tenant has available quota. If not, either reject, queue, or preempt lower-priority jobs. Use a scheduler that enforces fairness (e.g., weighted fair queuing, DRF) and supports preemption.

4. Enforce and monitor

Enforce quotas at the GPU allocation layer (e.g., Kubernetes device plugin, custom scheduler). Emit metrics for usage, quota violations, and fairness (e.g., Jain's fairness index). Set up alerts for abuse.

5. Handle edge cases and evolution

Discuss how to handle bursty workloads, quota changes, and failures. Consider a feedback loop to adjust quotas dynamically based on demand and priority.

Key Points to Mention

  • Hierarchical quotas (tenant, team, user) with inheritance and borrowing
  • Fairness algorithms: max-min fairness, weighted fair queuing, dominant resource fairness
  • Admission control and preemption to prevent starvation
  • Enforcement mechanisms: Kubernetes ResourceQuota, custom scheduler, GPU device plugin
  • Observability: metrics, logging, and fairness index
  • Trade-offs: strict isolation vs. utilization, complexity vs. simplicity

AI-generated suggestions, not part of the candidate's original notes. May be inaccurate — verify before relying on them.

Q6

How would training code and data be stored and made available to the compute nodes where jobs actually run?

System DesignTechnical Trade-offs
Author's notes

Container registry for code, object storage for training data.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Start by clarifying the scale and constraints (e.g., dataset size, training frequency, compute environment), then propose a layered storage architecture that separates code, data, and artifacts. Explain how each layer is versioned, cached, and accessed by compute nodes, emphasizing trade-offs between performance, cost, and complexity.

Pro tip: Mention that code and data should be treated as immutable, versioned artifacts, and that caching strategies (e.g., node-local SSD, distributed cache) are critical to avoid I/O bottlenecks at scale.

1. Clarify requirements and constraints

Ask about dataset size, update frequency, compute node types, network topology, and security/compliance needs to tailor the solution.

2. Design storage layers

Propose separate storage for code (e.g., Git, container registry), training data (e.g., object store like S3, HDFS), and artifacts (e.g., model checkpoints).

3. Define access and distribution mechanisms

Explain how compute nodes fetch code (e.g., container images, git clone) and data (e.g., mount distributed filesystem, download from object store, use data loader with caching).

4. Address performance and scalability

Discuss caching (node-local, distributed), data sharding, prefetching, and network optimizations to reduce latency and avoid bottlenecks.

5. Ensure versioning, reproducibility, and security

Describe how to version code and data (e.g., Git SHA, dataset versioning), enforce access controls, and enable reproducibility.

Key Points to Mention

  • Use of object storage (e.g., S3) for large datasets with versioning and lifecycle policies.
  • Containerization (e.g., Docker) for code packaging and dependency management.
  • Distributed file systems (e.g., HDFS, Lustre) or parallel file systems for high-throughput access.
  • Caching strategies: node-local SSD, distributed cache (e.g., Alluxio), or memory caching.
  • Data loading libraries (e.g., PyTorch DataLoader, TensorFlow tf.data) with prefetching and sharding.
  • Security: encryption at rest/in transit, IAM roles, and network isolation.

AI-generated suggestions, not part of the candidate's original notes. May be inaccurate — verify before relying on them.

Q7

What would your observability setup look like for this system, and how would you expose logs and metrics to users?

System DesignProduct Analytics & Metrics
Author's notes

Metrics pipeline from workers to a time-series store, job logs streamed to object storage and tailed via the status API.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Start by clarifying the system's components and user-facing goals, then outline a layered observability stack covering metrics, logs, and traces. Explain how you would expose relevant data to users through dashboards, alerts, and self-service tools, emphasizing actionable insights.

Pro tip: Frame observability as a product feature: focus on what users need to know to trust and operate the system, not just on collecting data. Mention SLOs and error budgets to show you connect reliability to business value.

1. Clarify system and user needs

Ask questions to understand the system architecture, critical user journeys, and who the users are (e.g., internal engineers, external customers). Identify what metrics and logs would be most valuable to them.

2. Design the observability stack

Propose tools for metrics (e.g., Prometheus), logs (e.g., ELK), and traces (e.g., Jaeger), ensuring they integrate with the system. Discuss instrumentation, data collection, and storage considerations.

3. Define what to expose and how

Decide which metrics (e.g., latency, error rates, throughput) and logs (e.g., request IDs, error details) to surface. Plan user-facing dashboards, APIs, or embedded views that present this data clearly.

4. Implement alerting and self-service

Set up alerts based on SLOs and error budgets, and provide users with self-service querying and filtering capabilities. Ensure alerts are actionable and routed to the right teams.

5. Iterate and govern

Establish processes for reviewing observability coverage, managing costs, and evolving the setup as the system grows. Include data retention policies and access controls.

Key Points to Mention

  • The three pillars of observability: metrics, logs, and traces, and how they complement each other.
  • Service Level Objectives (SLOs) and error budgets to align observability with user expectations.
  • User-facing dashboards and self-service tools (e.g., Grafana, custom portals) for transparency.
  • Alerting strategies: threshold-based vs. anomaly detection, and avoiding alert fatigue.
  • Data retention, sampling, and cost management for high-volume telemetry.
  • Security and access control: ensuring users only see data they are authorized to access.

AI-generated suggestions, not part of the candidate's original notes. May be inaccurate — verify before relying on them.