PracHub
QuestionsPremiumCoachesLearningGuidesInterview Prep
|Home/Coding & Algorithms/CloudKitchens

Design an in-memory cloud storage system

Last updated: Mar 29, 2026

Quick Overview

This question evaluates data modeling, stateful system design, and algorithmic reasoning for enforcing invariants such as a global namespace, single ownership, and per-user storage quotas.

  • Medium
  • CloudKitchens
  • Coding & Algorithms
  • Software Engineer

Design an in-memory cloud storage system

Company: CloudKitchens

Role: Software Engineer

Category: Coding & Algorithms

Difficulty: Medium

Interview Round: Technical Screen

Design and implement an in-memory cloud storage system that maps file paths to metadata and supports multi-user quotas. Use simple data structures; performance optimizations are not required. Constraints and invariants: - The filesystem namespace is global: each file path is unique across all users. - Each file is owned by exactly one user. - For any non-admin user, the total size of their files must not exceed their capacity at any time. - The special user "admin" has unlimited capacity; Level 1 operations are performed as admin. - Sorting rule used anywhere it applies: by size descending, then by name in lexicographical (ASCII) order ascending as a tie-breaker. Level 1 — basic file manipulation (admin by default): - add_file(self, name: str, size: int) -> bool: Add a new file. Fail if name already exists. Return True on success, False otherwise. - get_file_size(self, name: str) -> int | None: Return the size if the file exists, else None. - delete_file(self, name: str) -> int | None: Delete the file and return its size if it existed, else None. Level 2 — top-N by size with name filtering (per-user): - get_n_largest(self, user_id: str, prefix: str | None, suffix: str | None, n: int) -> list[str]: Among files owned by user_id whose names start with prefix (if prefix is not None/empty) and end with suffix (if suffix is not None/empty), return the names of the top n files sorted by the rule above. If fewer than n match, return all. If none match, return []. Level 3 — users, quotas, merging, and capacity adjustments: - add_user(self, user_id: str, capacity: int) -> bool: Create a user with the given capacity. Fail if user_id already exists. Return True on success, False otherwise. - add_file_by(self, user_id: str, name: str, size: int) -> int | None: Same behavior as add_file, but the file is owned by user_id. If adding the file would exceed the user’s capacity, the operation fails. On success, return the user’s remaining capacity (capacity − total_owned_size), else None. - adjust_capacity(self, user_id: str, new_capacity: int) -> int | None: Change the user’s capacity. If the new capacity is smaller than current usage, repeatedly delete the user’s largest files (using the sorting rule above to break ties) until total size ≤ new_capacity or no files remain. Return the number of files deleted, or None if user_id does not exist. - merge_users(self, target_id: str, source_id: str) -> int | None: Move all files owned by source_id into target_id. If a moved file name conflicts with an existing global name, skip that file. Ensure target_id’s capacity invariant is maintained; if necessary, delete target_id’s largest files (per the same deletion rule) until within capacity. After the merge, delete source_id and its backup (if any); target_id’s backup is not modified. Return the count of files successfully moved, or None if either user does not exist. Level 4 — backup/restore and size transform operations: - backup_user(self, user_id: str) -> int | None: Snapshot the current set of files (names and sizes) owned by user_id into a separate backup store, overwriting any prior backup for that user. Return the number of files backed up, or None if user_id does not exist. - restore_user(self, user_id: str) -> int | None: Replace the user’s current files with the latest backup snapshot. If there is no backup, delete all of the user’s files. When restoring, if a file from the backup conflicts with an existing global name owned by another user, skip that file. Do not change the user’s capacity value as part of restore. Return the number of files restored, or None if user_id does not exist. - compress_user(self, user_id: str) -> int | None: For each file owned by user_id, set size := floor(size / 2). Return the number of files updated, or None if user_id does not exist. - decompress_user(self, user_id: str) -> int | None: For each file owned by user_id, set size := size * 2, then ensure the capacity invariant holds; if it does not, delete the user’s largest files (per the same deletion rule) until within capacity. Return the number of files remaining after decompression, or None if user_id does not exist. Notes: - Implement exact lexicographical tie-breaking on names when sizes are equal. - Comparisons for prefix/suffix may be performed directly on strings; no trie or priority queue is required. - All method names, arguments, and return types should match exactly as specified above.

Quick Answer: This question evaluates data modeling, stateful system design, and algorithmic reasoning for enforcing invariants such as a global namespace, single ownership, and per-user storage quotas.

Related Interview Questions

  • Implement menu parser and serializer - CloudKitchens (medium)
  • Design a menu manager with enums - CloudKitchens (Medium)
  • Design receipt system with combo discounts - CloudKitchens (Medium)
  • Implement concurrent order-accept/pickup simulator - CloudKitchens (medium)
  • Answer static and streaming Top-K queries - CloudKitchens (medium)
CloudKitchens logo
CloudKitchens
Sep 6, 2025, 12:00 AM
Software Engineer
Technical Screen
Coding & Algorithms
8
0

Design and implement an in-memory cloud storage system that maps file paths to metadata and supports multi-user quotas. Use simple data structures; performance optimizations are not required.

Constraints and invariants:

  • The filesystem namespace is global: each file path is unique across all users.
  • Each file is owned by exactly one user.
  • For any non-admin user, the total size of their files must not exceed their capacity at any time.
  • The special user "admin" has unlimited capacity; Level 1 operations are performed as admin.
  • Sorting rule used anywhere it applies: by size descending, then by name in lexicographical (ASCII) order ascending as a tie-breaker.

Level 1 — basic file manipulation (admin by default):

  • add_file(self, name: str, size: int) -> bool: Add a new file. Fail if name already exists. Return True on success, False otherwise.
  • get_file_size(self, name: str) -> int | None: Return the size if the file exists, else None.
  • delete_file(self, name: str) -> int | None: Delete the file and return its size if it existed, else None.

Level 2 — top-N by size with name filtering (per-user):

  • get_n_largest(self, user_id: str, prefix: str | None, suffix: str | None, n: int) -> list[str]: Among files owned by user_id whose names start with prefix (if prefix is not None/empty) and end with suffix (if suffix is not None/empty), return the names of the top n files sorted by the rule above. If fewer than n match, return all. If none match, return [].

Level 3 — users, quotas, merging, and capacity adjustments:

  • add_user(self, user_id: str, capacity: int) -> bool: Create a user with the given capacity. Fail if user_id already exists. Return True on success, False otherwise.
  • add_file_by(self, user_id: str, name: str, size: int) -> int | None: Same behavior as add_file, but the file is owned by user_id. If adding the file would exceed the user’s capacity, the operation fails. On success, return the user’s remaining capacity (capacity − total_owned_size), else None.
  • adjust_capacity(self, user_id: str, new_capacity: int) -> int | None: Change the user’s capacity. If the new capacity is smaller than current usage, repeatedly delete the user’s largest files (using the sorting rule above to break ties) until total size ≤ new_capacity or no files remain. Return the number of files deleted, or None if user_id does not exist.
  • merge_users(self, target_id: str, source_id: str) -> int | None: Move all files owned by source_id into target_id. If a moved file name conflicts with an existing global name, skip that file. Ensure target_id’s capacity invariant is maintained; if necessary, delete target_id’s largest files (per the same deletion rule) until within capacity. After the merge, delete source_id and its backup (if any); target_id’s backup is not modified. Return the count of files successfully moved, or None if either user does not exist.

Level 4 — backup/restore and size transform operations:

  • backup_user(self, user_id: str) -> int | None: Snapshot the current set of files (names and sizes) owned by user_id into a separate backup store, overwriting any prior backup for that user. Return the number of files backed up, or None if user_id does not exist.
  • restore_user(self, user_id: str) -> int | None: Replace the user’s current files with the latest backup snapshot. If there is no backup, delete all of the user’s files. When restoring, if a file from the backup conflicts with an existing global name owned by another user, skip that file. Do not change the user’s capacity value as part of restore. Return the number of files restored, or None if user_id does not exist.
  • compress_user(self, user_id: str) -> int | None: For each file owned by user_id, set size := floor(size / 2). Return the number of files updated, or None if user_id does not exist.
  • decompress_user(self, user_id: str) -> int | None: For each file owned by user_id, set size := size * 2, then ensure the capacity invariant holds; if it does not, delete the user’s largest files (per the same deletion rule) until within capacity. Return the number of files remaining after decompression, or None if user_id does not exist.

Notes:

  • Implement exact lexicographical tie-breaking on names when sizes are equal.
  • Comparisons for prefix/suffix may be performed directly on strings; no trie or priority queue is required.
  • All method names, arguments, and return types should match exactly as specified above.

Submit Your Answer to Earn 20XP

Sign in to leave a comment

Loading comments...

Browse More Questions

More Coding & Algorithms•More CloudKitchens•More Software Engineer•CloudKitchens Software Engineer•CloudKitchens Coding & Algorithms•Software Engineer Coding & Algorithms
PracHub

Master your tech interviews with 8,000+ real questions from top companies.

Product

  • Questions
  • Learning Tracks
  • Interview Guides
  • Resources
  • Premium
  • For Universities
  • Student Access

Browse

  • By Company
  • By Role
  • By Category
  • Topic Hubs
  • SQL Questions
  • Compare Platforms
  • Discord Community

Support

  • support@prachub.com
  • (916) 541-4762

Legal

  • Privacy Policy
  • Terms of Service
  • About Us

© 2026 PracHub. All rights reserved.