or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

backend-cores.mdcache-management.mdcore-decorator.mdglobal-configuration.mdindex.md

backend-cores.mddocs/

0

# Backend Cores

1

2

Cachier supports multiple storage backends to meet different caching requirements, from simple in-memory caching to distributed cross-machine caching solutions. Each backend is optimized for specific use cases and environments.

3

4

## Available Backends

5

6

```python { .api }

7

Backend = Literal["pickle", "mongo", "memory", "redis", "sql"]

8

```

9

10

## Capabilities

11

12

### Pickle Backend (Default)

13

14

File-based persistent caching using Python's pickle serialization:

15

16

```python { .api }

17

@cachier(backend='pickle')

18

def cached_function(args):

19

return computation(args)

20

21

# With custom cache directory

22

@cachier(

23

backend='pickle',

24

cache_dir='/path/to/cache',

25

pickle_reload=True,

26

separate_files=False

27

)

28

def file_cached_function(args):

29

return computation(args)

30

```

31

32

**Pickle Backend Parameters**:

33

- `cache_dir`: Directory for cache files (default: `~/.cachier/`)

34

- `pickle_reload`: Reload cache on each read for thread safety (default: `True`)

35

- `separate_files`: Split cache into separate files per argument set (default: `False`)

36

37

**Use Cases**:

38

- Single-machine applications

39

- Persistent caching across application restarts

40

- Development and testing environments

41

- Functions with complex return types

42

43

**Advantages**:

44

- No external dependencies

45

- Handles any picklable Python object

46

- Persistent across restarts

47

- File-based inspection possible

48

49

**Limitations**:

50

- Single-machine only

51

- Not suitable for high-concurrency scenarios

52

- Pickle security considerations with untrusted data

53

54

### Memory Backend

55

56

In-memory caching for fastest access within a single process:

57

58

```python { .api }

59

@cachier(backend='memory')

60

def memory_cached_function(args):

61

return computation(args)

62

63

# With calculation timeout

64

@cachier(

65

backend='memory',

66

wait_for_calc_timeout=30

67

)

68

def concurrent_memory_function(args):

69

return computation(args)

70

```

71

72

**Memory Backend Parameters**:

73

- `wait_for_calc_timeout`: Max wait time for ongoing calculations (default: `0` - wait forever)

74

75

**Use Cases**:

76

- High-performance applications requiring fastest access

77

- Temporary caching within application lifecycle

78

- Testing and development

79

- Functions called frequently within short time periods

80

81

**Advantages**:

82

- Fastest access times

83

- No I/O overhead

84

- Thread-safe within process

85

- No external dependencies

86

87

**Limitations**:

88

- Lost on application restart

89

- Memory usage grows with cache size

90

- Single-process only

91

92

### MongoDB Backend

93

94

Distributed caching using MongoDB for cross-machine cache sharing:

95

96

```python { .api }

97

def get_mongo_collection():

98

import pymongo

99

client = pymongo.MongoClient('mongodb://localhost:27017/')

100

return client.cache_db.function_cache

101

102

@cachier(

103

backend='mongo',

104

mongetter=get_mongo_collection,

105

wait_for_calc_timeout=60

106

)

107

def distributed_function(args):

108

return computation(args)

109

```

110

111

**MongoDB Backend Parameters**:

112

- `mongetter`: Callable returning `pymongo.Collection` with write permissions

113

- `wait_for_calc_timeout`: Max wait time for ongoing calculations (default: `0`)

114

115

**Use Cases**:

116

- Distributed applications across multiple machines

117

- Microservices sharing computation results

118

- Cloud deployments with shared state

119

- Long-running computations with high reuse

120

121

**Advantages**:

122

- Cross-machine cache sharing

123

- Persistent and durable storage

124

- Handles concurrent access well

125

- Scalable with MongoDB clusters

126

127

**Limitations**:

128

- Requires MongoDB infrastructure

129

- Network latency for cache operations

130

- Additional dependency (pymongo)

131

- Serialization limitations

132

133

### Redis Backend

134

135

High-performance distributed caching using Redis:

136

137

```python { .api }

138

def get_redis_client():

139

import redis

140

return redis.Redis(host='localhost', port=6379, db=0)

141

142

@cachier(

143

backend='redis',

144

redis_client=get_redis_client,

145

wait_for_calc_timeout=30

146

)

147

def redis_cached_function(args):

148

return computation(args)

149

150

# Using Redis client instance directly

151

import redis

152

redis_client = redis.Redis(host='cache-server', port=6379)

153

154

@cachier(

155

backend='redis',

156

redis_client=redis_client

157

)

158

def fast_distributed_function(args):

159

return computation(args)

160

```

161

162

**Redis Backend Parameters**:

163

- `redis_client`: Redis client instance or callable returning Redis client

164

- `wait_for_calc_timeout`: Max wait time for ongoing calculations (default: `0`)

165

166

**Use Cases**:

167

- High-performance distributed caching

168

- Real-time applications requiring fast cache access

169

- Session storage and temporary data

170

- Microservices with shared cache layer

171

172

**Advantages**:

173

- Very fast access times

174

- Built-in expiration support

175

- Cross-machine cache sharing

176

- Battle-tested for high concurrency

177

178

**Limitations**:

179

- Requires Redis infrastructure

180

- Memory-based storage (though persistent options available)

181

- Additional dependency (redis-py)

182

183

### SQL Backend

184

185

Database-backed caching using SQLAlchemy for enterprise environments:

186

187

```python { .api }

188

# Using connection string

189

@cachier(

190

backend='sql',

191

sql_engine='postgresql://user:pass@localhost/cache_db'

192

)

193

def sql_cached_function(args):

194

return computation(args)

195

196

# Using SQLAlchemy Engine

197

from sqlalchemy import create_engine

198

199

engine = create_engine('sqlite:///cache.db')

200

201

@cachier(

202

backend='sql',

203

sql_engine=engine

204

)

205

def database_cached_function(args):

206

return computation(args)

207

208

# Using callable for lazy connection

209

def get_sql_engine():

210

return create_engine('mysql://user:pass@dbserver/cache')

211

212

@cachier(

213

backend='sql',

214

sql_engine=get_sql_engine,

215

wait_for_calc_timeout=45

216

)

217

def enterprise_function(args):

218

return computation(args)

219

```

220

221

**SQL Backend Parameters**:

222

- `sql_engine`: SQLAlchemy connection string, Engine instance, or callable returning Engine

223

- `wait_for_calc_timeout`: Max wait time for ongoing calculations (default: `0`)

224

225

**Use Cases**:

226

- Enterprise applications with existing database infrastructure

227

- Audit trails and cache inspection requirements

228

- Integration with existing data management policies

229

- Long-term cache persistence with backup/recovery

230

231

**Advantages**:

232

- Leverages existing database infrastructure

233

- ACID properties and transactional consistency

234

- Advanced querying and management capabilities

235

- Integration with enterprise monitoring and backup

236

237

**Limitations**:

238

- Database overhead for simple caching needs

239

- Requires SQLAlchemy dependency

240

- Potential performance overhead compared to specialized cache stores

241

242

## Backend Selection Guide

243

244

### Choose Pickle When:

245

- Single-machine deployment

246

- Complex Python objects to cache

247

- Simple setup with no external dependencies

248

- Development and testing environments

249

250

### Choose Memory When:

251

- Highest performance requirements

252

- Temporary caching within application lifecycle

253

- Single-process applications

254

- Frequent cache access patterns

255

256

### Choose MongoDB When:

257

- Multi-machine distributed caching needed

258

- Document-oriented data fits well

259

- MongoDB already in infrastructure

260

- Complex query requirements on cached data

261

262

### Choose Redis When:

263

- High-performance distributed caching required

264

- Real-time applications

265

- Built-in expiration features needed

266

- Redis already in infrastructure

267

268

### Choose SQL When:

269

- Enterprise database infrastructure exists

270

- ACID properties required

271

- Advanced querying and reporting on cache needed

272

- Integration with existing data governance

273

274

## Usage Examples

275

276

### Backend Comparison

277

278

```python

279

from cachier import cachier

280

import time

281

282

# Same function with different backends

283

def expensive_computation(n):

284

time.sleep(1) # Simulate expensive operation

285

return sum(i**2 for i in range(n))

286

287

# Pickle - for persistent single-machine caching

288

@cachier(backend='pickle')

289

def pickle_version(n):

290

return expensive_computation(n)

291

292

# Memory - for fastest access

293

@cachier(backend='memory')

294

def memory_version(n):

295

return expensive_computation(n)

296

297

# MongoDB - for distributed caching

298

@cachier(backend='mongo', mongetter=get_mongo_collection)

299

def mongo_version(n):

300

return expensive_computation(n)

301

302

# Redis - for high-performance distributed caching

303

@cachier(backend='redis', redis_client=get_redis_client)

304

def redis_version(n):

305

return expensive_computation(n)

306

307

# SQL - for enterprise database-backed caching

308

@cachier(backend='sql', sql_engine='sqlite:///cache.db')

309

def sql_version(n):

310

return expensive_computation(n)

311

```

312

313

### Production Configuration Examples

314

315

```python

316

import os

317

from cachier import cachier, set_global_params

318

319

# Development environment - use memory for speed

320

if os.getenv('ENV') == 'development':

321

set_global_params(backend='memory')

322

323

# Production environment - use Redis cluster

324

elif os.getenv('ENV') == 'production':

325

import redis

326

redis_client = redis.Redis(

327

host=os.getenv('REDIS_HOST', 'cache-cluster'),

328

port=int(os.getenv('REDIS_PORT', 6379)),

329

password=os.getenv('REDIS_PASSWORD'),

330

ssl=True

331

)

332

set_global_params(

333

backend='redis',

334

redis_client=redis_client,

335

wait_for_calc_timeout=60

336

)

337

338

# Testing environment - use pickle with temp directory

339

else:

340

import tempfile

341

set_global_params(

342

backend='pickle',

343

cache_dir=tempfile.mkdtemp()

344

)

345

346

@cachier() # Uses environment-appropriate backend

347

def application_function(data):

348

return process_data(data)

349

```

350

351

### Multi-Backend Strategy

352

353

```python

354

from cachier import cachier

355

356

# Fast local cache for frequently accessed data

357

@cachier(backend='memory', stale_after=timedelta(minutes=5))

358

def local_fast_cache(key):

359

# Check distributed cache first

360

return distributed_cache(key)

361

362

# Distributed cache for shared data across instances

363

@cachier(backend='redis', redis_client=redis_client, stale_after=timedelta(hours=1))

364

def distributed_cache(key):

365

# Fallback to persistent storage

366

return persistent_cache(key)

367

368

# Persistent backup cache for rarely accessed data

369

@cachier(backend='sql', sql_engine=db_engine, stale_after=timedelta(days=1))

370

def persistent_cache(key):

371

# Original data source

372

return expensive_data_fetch(key)

373

374

# This creates a three-tier caching strategy:

375

# 1. Memory (fastest, 5min expiry)

376

# 2. Redis (fast distributed, 1hr expiry)

377

# 3. SQL (persistent backup, 1day expiry)

378

# 4. Original source (slowest)

379

```

380

381

## Backend-Specific Type Definitions

382

383

```python { .api }

384

from typing import Callable, Union, TYPE_CHECKING

385

386

if TYPE_CHECKING:

387

import pymongo.collection

388

import redis

389

390

HashFunc = Callable[..., str]

391

Mongetter = Callable[[], "pymongo.collection.Collection"]

392

RedisClient = Union["redis.Redis", Callable[[], "redis.Redis"]]

393

Backend = Literal["pickle", "mongo", "memory", "redis", "sql"]

394

```

395

396

These type definitions ensure proper type checking and IDE support when configuring different backends.