RUNLOCALAIv38
->Will it run?Best GPUCompareTroubleshootStartLearnPulseModelsHardwareToolsBench
Run check
RUNLOCALAI

Independently operated catalog for local-AI hardware and software. Hand-written verdicts. Source-cited claims. Reproducible commands when we have them.

OP·Fredoline Eruo
DIR
  • Models
  • Hardware
  • Tools
  • Benchmarks
TOOLS
  • Will it run?
  • Compare hardware
  • Cost vs cloud
  • Choose my GPU
  • Prompting kits
  • Quick answers
REF
  • All buyer guides
  • Learn local AI
  • Methodology
  • Glossary
  • Errors KB
  • Trust
EDITOR
  • About
  • Author
  • How we make money
  • Editorial policy
  • Contact
LEGAL
  • Privacy
  • Terms
  • Sitemap
MAIL · MONTHLY DIGEST
Get monthly local AI changes
Monthly recap. No spam.
DISCLOSURE

Some links on this site are affiliate links (Amazon Associates and other first-class retailers). When you buy through them, we earn a small commission at no extra cost to you. Affiliate links do not influence our verdicts — there are cards we rate highly that we don't have affiliate relationships with, and cards that sell well that we refuse to recommend. Read more →

© 2026 runlocalai.coIndependently operated
RUNLOCALAI · v38
  1. >
  2. Home
  3. /Learn
  4. /Courses
  5. /AI-Powered SaaS Products
  6. /Ch. 3
AI-Powered SaaS Products

03. Tenant Isolation

Chapter 3 of 24 · 15 min
KEY INSIGHT

Tenant isolation goes beyond database separation—cache keys, file storage, external API calls, and logs must all respect tenant boundaries. Data isolation failures typically occur at system boundaries. The database query is properly filtered, but the cache returns another tenant's data, or the S3 bucket contains mixed tenant files. A defense-in-depth approach treats every data access point as a potential breach vector. Cache isolation prevents tenant data leakage in Redis or Memcached. Every cache key must include the tenant identifier. ```python import redis from functools import wraps redis_client = redis.Redis(host="localhost", port=6379, db=0) def tenant_cache(key_template: str, ttl: int = 300): """Decorator that prefixes cache keys with tenant ID.""" def decorator(func): @wraps(func) def wrapper(tenant_id: str, *args, **kwargs): cache_key = f"tenant:{tenant_id}:{key_template.format(*args, **kwargs)}" cached = redis_client.get(cache_key) if cached: return json.loads(cached) result = func(tenant_id, *args, **kwargs) redis_client.setex(cache_key, ttl, json.dumps(result)) return result return wrapper return decorator @tenant_cache("models:{model_id}", ttl=600) def get_model_config(tenant_id: str, model_id: str) -> dict: return db.query(ModelConfig).filter_by( tenant_id=tenant_id, id=model_id ).first() ``` File storage isolation matters when tenants upload files or when the system generates outputs. Object stores like S3 or MinIO require careful bucket and key design. ```python import boto3 from typing import BinaryIO class TenantFileStore: def __init__(self, bucket_name: str): self.s3 = boto3.client("s3") self.bucket = bucket_name def _validate_path(self, tenant_id: str, key: str): """Prevent path traversal attacks.""" if ".." in key or key.startswith("/"): raise ValueError("Invalid path") # Enforce tenant prefix expected_prefix = f"tenants/{tenant_id}/" if not key.startswith(expected_prefix): raise ValueError(f"Path must start with {expected_prefix}") def upload(self, tenant_id: str, key: str, file_obj: BinaryIO): self._validate_path(tenant_id, key) s3_key = f"tenants/{tenant_id}/{key}" self.s3.upload_fileobj(file_obj, self.bucket, s3_key) ``` Failure mode: omitting validation in file operations allows one tenant to overwrite another tenant's files or access sensitive data. The `_validate_path` function prevents directory traversal but a missing check anywhere in the upload/download chain creates vulnerability.

EXERCISE

Audit this code for isolation vulnerabilities. Write a test that demonstrates what happens when get_model_config is called with the wrong tenant_id. How would you add integration test coverage for tenant isolation?

← Chapter 2
Multi-Tenant Design
Chapter 4 →
User Management