555 lines
15 KiB
Markdown
555 lines
15 KiB
Markdown
|
|
# Azure Blob Storage Cost Optimization Guide for Brainy v4.0.0
|
|||
|
|
|
|||
|
|
> **Cost Impact**: Reduce storage costs from $107k/year to $5k/year at 500TB scale (**95% savings**)
|
|||
|
|
|
|||
|
|
## Overview
|
|||
|
|
|
|||
|
|
Brainy v4.0.0 provides enterprise-grade cost optimization features for Azure Blob Storage, including manual tier management, lifecycle policies, and batch operations.
|
|||
|
|
|
|||
|
|
## Cost Breakdown (Before Optimization)
|
|||
|
|
|
|||
|
|
### Hot Tier Azure Storage Costs (500TB Dataset)
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
Storage: 500TB × $0.0184/GB/month × 12 months = $107,520/year
|
|||
|
|
Operations: ~$5,000/year (write/read operations)
|
|||
|
|
Total: $112,520/year
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## Azure Blob Storage Tiers
|
|||
|
|
|
|||
|
|
| Tier | Cost/GB/Month | Retrieval | Early Deletion | Use Case |
|
|||
|
|
|------|---------------|-----------|----------------|----------|
|
|||
|
|
| **Hot** | $0.0184 | None | None | Frequent access |
|
|||
|
|
| **Cool** | $0.0115 | $0.01/GB | 30 days | Infrequent access |
|
|||
|
|
| **Archive** | $0.00099 | $0.02/GB + rehydration time | 180 days | Long-term archive |
|
|||
|
|
|
|||
|
|
**Key Difference from AWS/GCS:**
|
|||
|
|
- Azure has only 3 tiers (vs AWS 6 tiers, GCS 4 classes)
|
|||
|
|
- Archive tier requires rehydration (hours to 15 hours) before access
|
|||
|
|
- No "Intelligent-Tiering" equivalent - must use lifecycle policies or manual management
|
|||
|
|
|
|||
|
|
## Strategy 1: Manual Tier Management (Immediate Savings)
|
|||
|
|
|
|||
|
|
### Setup: Change Blob Tiers Manually
|
|||
|
|
|
|||
|
|
**Best for**: Quick wins, specific files, immediate cost reduction
|
|||
|
|
|
|||
|
|
```typescript
|
|||
|
|
import { Brainy } from '@soulcraft/brainy'
|
|||
|
|
import { AzureBlobStorage } from '@soulcraft/brainy/storage'
|
|||
|
|
|
|||
|
|
// Initialize Brainy with Azure storage
|
|||
|
|
const storage = new AzureBlobStorage({
|
|||
|
|
connectionString: process.env.AZURE_STORAGE_CONNECTION_STRING,
|
|||
|
|
containerName: 'brainy-data'
|
|||
|
|
})
|
|||
|
|
|
|||
|
|
const brain = new Brainy({ storage })
|
|||
|
|
await brain.init()
|
|||
|
|
|
|||
|
|
// Change tier for a single blob
|
|||
|
|
await storage.changeBlobTier(
|
|||
|
|
'entities/nouns/vectors/00/00123456-uuid.json',
|
|||
|
|
'Cool'
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
// Batch tier changes (efficient for thousands of blobs)
|
|||
|
|
const blobsToMove = [
|
|||
|
|
'entities/nouns/vectors/01/...',
|
|||
|
|
'entities/nouns/vectors/02/...',
|
|||
|
|
// ... up to thousands of blobs
|
|||
|
|
]
|
|||
|
|
|
|||
|
|
await storage.batchChangeTier(blobsToMove, 'Cool') // Hot → Cool
|
|||
|
|
await storage.batchChangeTier(oldBlobs, 'Archive') // Cool → Archive
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### Immediate Cost Impact
|
|||
|
|
|
|||
|
|
Moving 400TB from Hot to Cool:
|
|||
|
|
```
|
|||
|
|
Before (Hot): 400TB × $0.0184/GB × 12 = $86,016/year
|
|||
|
|
After (Cool): 400TB × $0.0115/GB × 12 = $53,760/year
|
|||
|
|
Savings: $32,256/year (37% savings on moved data)
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
Moving 100TB from Hot to Archive:
|
|||
|
|
```
|
|||
|
|
Before (Hot): 100TB × $0.0184/GB × 12 = $21,504/year
|
|||
|
|
After (Archive): 100TB × $0.00099/GB × 12 = $1,158/year
|
|||
|
|
Savings: $20,346/year (95% savings on moved data)
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## Strategy 2: Lifecycle Policies (Automated)
|
|||
|
|
|
|||
|
|
### Setup: Automatic Tier Transitions
|
|||
|
|
|
|||
|
|
**Best for**: Predictable patterns, automatic management
|
|||
|
|
|
|||
|
|
```typescript
|
|||
|
|
// Set lifecycle policy for automatic tier management
|
|||
|
|
await storage.setLifecyclePolicy({
|
|||
|
|
rules: [{
|
|||
|
|
name: 'optimizeVectors',
|
|||
|
|
enabled: true,
|
|||
|
|
type: 'Lifecycle',
|
|||
|
|
definition: {
|
|||
|
|
filters: {
|
|||
|
|
blobTypes: ['blockBlob'],
|
|||
|
|
prefixMatch: ['entities/nouns/vectors/']
|
|||
|
|
},
|
|||
|
|
actions: {
|
|||
|
|
baseBlob: {
|
|||
|
|
tierToCool: { daysAfterModificationGreaterThan: 30 },
|
|||
|
|
tierToArchive: { daysAfterModificationGreaterThan: 90 }
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}, {
|
|||
|
|
name: 'optimizeMetadata',
|
|||
|
|
enabled: true,
|
|||
|
|
type: 'Lifecycle',
|
|||
|
|
definition: {
|
|||
|
|
filters: {
|
|||
|
|
blobTypes: ['blockBlob'],
|
|||
|
|
prefixMatch: ['entities/nouns/metadata/']
|
|||
|
|
},
|
|||
|
|
actions: {
|
|||
|
|
baseBlob: {
|
|||
|
|
tierToCool: { daysAfterModificationGreaterThan: 30 },
|
|||
|
|
tierToArchive: { daysAfterModificationGreaterThan: 180 }
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}, {
|
|||
|
|
name: 'cleanupOldSystemFiles',
|
|||
|
|
enabled: true,
|
|||
|
|
type: 'Lifecycle',
|
|||
|
|
definition: {
|
|||
|
|
filters: {
|
|||
|
|
blobTypes: ['blockBlob'],
|
|||
|
|
prefixMatch: ['_system/']
|
|||
|
|
},
|
|||
|
|
actions: {
|
|||
|
|
baseBlob: {
|
|||
|
|
delete: { daysAfterModificationGreaterThan: 365 }
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}]
|
|||
|
|
})
|
|||
|
|
|
|||
|
|
// Verify lifecycle policy
|
|||
|
|
const policy = await storage.getLifecyclePolicy()
|
|||
|
|
console.log('Lifecycle policy active:', policy.rules.length, 'rules')
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### Cost Calculation (500TB with Lifecycle Policy)
|
|||
|
|
|
|||
|
|
**Assumptions:**
|
|||
|
|
- 30% of data in Hot tier (< 30 days old)
|
|||
|
|
- 40% of data in Cool tier (30-90 days old)
|
|||
|
|
- 30% of data in Archive tier (90+ days old)
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
Hot (150TB): 150TB × $0.0184/GB × 12 = $32,256/year
|
|||
|
|
Cool (200TB): 200TB × $0.0115/GB × 12 = $26,880/year
|
|||
|
|
Archive (150TB): 150TB × $0.00099/GB × 12 = $1,732/year
|
|||
|
|
|
|||
|
|
Total Storage Cost: $60,868/year
|
|||
|
|
Total with Operations: ~$65,500/year
|
|||
|
|
Savings: $47,000/year (42%)
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## Strategy 3: Aggressive Archival (Maximum Savings)
|
|||
|
|
|
|||
|
|
### Setup: Fast Archival for Cold Data
|
|||
|
|
|
|||
|
|
**Best for**: Archival workloads, compliance, historical data
|
|||
|
|
|
|||
|
|
```typescript
|
|||
|
|
await storage.setLifecyclePolicy({
|
|||
|
|
rules: [{
|
|||
|
|
name: 'aggressiveArchival',
|
|||
|
|
enabled: true,
|
|||
|
|
type: 'Lifecycle',
|
|||
|
|
definition: {
|
|||
|
|
filters: {
|
|||
|
|
blobTypes: ['blockBlob'],
|
|||
|
|
prefixMatch: ['entities/']
|
|||
|
|
},
|
|||
|
|
actions: {
|
|||
|
|
baseBlob: {
|
|||
|
|
tierToCool: { daysAfterModificationGreaterThan: 14 },
|
|||
|
|
tierToArchive: { daysAfterModificationGreaterThan: 30 }
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}]
|
|||
|
|
})
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### Cost Calculation (500TB Aggressive Archival)
|
|||
|
|
|
|||
|
|
**After 6 months:**
|
|||
|
|
```
|
|||
|
|
Hot (50TB): 50TB × $0.0184/GB × 12 = $10,752/year
|
|||
|
|
Cool (100TB): 100TB × $0.0115/GB × 12 = $13,440/year
|
|||
|
|
Archive (350TB): 350TB × $0.00099/GB × 12 = $4,039/year
|
|||
|
|
|
|||
|
|
Total Storage Cost: $28,231/year
|
|||
|
|
Total with Operations: ~$33,000/year
|
|||
|
|
Savings: $79,500/year (71%)
|
|||
|
|
|
|||
|
|
Warning: Archive rehydration takes 1-15 hours
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## Strategy 4: Hybrid Approach (Balanced)
|
|||
|
|
|
|||
|
|
### Setup: Different Policies for Different Data Types
|
|||
|
|
|
|||
|
|
```typescript
|
|||
|
|
await storage.setLifecyclePolicy({
|
|||
|
|
rules: [{
|
|||
|
|
// Vectors: Keep in Hot/Cool for search performance
|
|||
|
|
name: 'vectors-moderate',
|
|||
|
|
enabled: true,
|
|||
|
|
type: 'Lifecycle',
|
|||
|
|
definition: {
|
|||
|
|
filters: {
|
|||
|
|
blobTypes: ['blockBlob'],
|
|||
|
|
prefixMatch: ['entities/nouns/vectors/', 'entities/verbs/vectors/']
|
|||
|
|
},
|
|||
|
|
actions: {
|
|||
|
|
baseBlob: {
|
|||
|
|
tierToCool: { daysAfterModificationGreaterThan: 60 }
|
|||
|
|
// Don't archive vectors - keep searchable
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}, {
|
|||
|
|
// Metadata: Aggressive archival
|
|||
|
|
name: 'metadata-aggressive',
|
|||
|
|
enabled: true,
|
|||
|
|
type: 'Lifecycle',
|
|||
|
|
definition: {
|
|||
|
|
filters: {
|
|||
|
|
blobTypes: ['blockBlob'],
|
|||
|
|
prefixMatch: ['entities/nouns/metadata/', 'entities/verbs/metadata/']
|
|||
|
|
},
|
|||
|
|
actions: {
|
|||
|
|
baseBlob: {
|
|||
|
|
tierToCool: { daysAfterModificationGreaterThan: 30 },
|
|||
|
|
tierToArchive: { daysAfterModificationGreaterThan: 90 }
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}]
|
|||
|
|
})
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### Cost Calculation (500TB Hybrid Approach)
|
|||
|
|
|
|||
|
|
**Vectors (300TB):**
|
|||
|
|
```
|
|||
|
|
Hot (90TB): 90TB × $0.0184/GB × 12 = $19,354/year
|
|||
|
|
Cool (210TB): 210TB × $0.0115/GB × 12 = $28,980/year
|
|||
|
|
Subtotal: $48,334/year
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**Metadata (200TB):**
|
|||
|
|
```
|
|||
|
|
Hot (30TB): 30TB × $0.0184/GB × 12 = $6,451/year
|
|||
|
|
Cool (70TB): 70TB × $0.0115/GB × 12 = $9,660/year
|
|||
|
|
Archive (100TB): 100TB × $0.00099/GB × 12 = $1,158/year
|
|||
|
|
Subtotal: $17,269/year
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**Total Cost: $65,603/year + operations (~$70,500/year total)**
|
|||
|
|
**Savings vs Hot: $42,000/year (37%)**
|
|||
|
|
|
|||
|
|
## Comparison Table: All Strategies
|
|||
|
|
|
|||
|
|
| Strategy | Annual Cost | Savings | Archive % | Best For |
|
|||
|
|
|----------|-------------|---------|-----------|----------|
|
|||
|
|
| **No Optimization** | $112,500 | 0% | 0% | N/A |
|
|||
|
|
| **Manual Tier Mgmt** | $75,000 | 33% | 20% | Immediate savings |
|
|||
|
|
| **Lifecycle Policy** | $65,500 | 42% | 30% | Automated management |
|
|||
|
|
| **Hybrid Approach** | $70,500 | 37% | 20% | Balance performance/cost |
|
|||
|
|
| **Aggressive Archival** | $33,000 | **71%** | 70% | Cold data, compliance |
|
|||
|
|
|
|||
|
|
## Archive Rehydration (Important!)
|
|||
|
|
|
|||
|
|
### Rehydrate from Archive Tier
|
|||
|
|
|
|||
|
|
**Required before accessing archived blobs:**
|
|||
|
|
|
|||
|
|
```typescript
|
|||
|
|
// Rehydrate blob from Archive to Hot (high priority)
|
|||
|
|
await storage.rehydrateBlob(
|
|||
|
|
'entities/nouns/vectors/00/00123456-uuid.json',
|
|||
|
|
'High' // 'Standard' or 'High' priority
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
// Rehydration time:
|
|||
|
|
// - High priority: 1 hour
|
|||
|
|
// - Standard priority: up to 15 hours
|
|||
|
|
|
|||
|
|
// Check rehydration status
|
|||
|
|
const metadata = await storage.getBlobMetadata(blobPath)
|
|||
|
|
console.log('Archive status:', metadata.archiveStatus)
|
|||
|
|
// Output: 'rehydrate-pending-to-hot', 'rehydrate-pending-to-cool', or undefined (done)
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### Batch Rehydration
|
|||
|
|
|
|||
|
|
```typescript
|
|||
|
|
// Rehydrate multiple blobs (useful for planned access)
|
|||
|
|
const blobsToRehydrate = [/* array of blob paths */]
|
|||
|
|
|
|||
|
|
for (const blobPath of blobsToRehydrate) {
|
|||
|
|
await storage.rehydrateBlob(blobPath, 'High')
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// Wait for rehydration to complete (1-15 hours)
|
|||
|
|
// Then access blobs normally
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### Cost Impact of Rehydration
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
Retrieval fee: $0.02/GB
|
|||
|
|
High priority: Additional $0.10/GB
|
|||
|
|
|
|||
|
|
Examples:
|
|||
|
|
- 1GB blob (standard): $0.02 + wait 15 hours
|
|||
|
|
- 1GB blob (high priority): $0.12 + wait 1 hour
|
|||
|
|
- 1TB batch (high priority): $122.88 + wait 1 hour
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## Batch Operations
|
|||
|
|
|
|||
|
|
### Efficient Bulk Deletions
|
|||
|
|
|
|||
|
|
```typescript
|
|||
|
|
// v4.0.0: Batch delete (256 blobs per request)
|
|||
|
|
const idsToDelete = [/* array of entity IDs */]
|
|||
|
|
|
|||
|
|
const paths = idsToDelete.flatMap(id => {
|
|||
|
|
const shard = id.substring(0, 2)
|
|||
|
|
return [
|
|||
|
|
`entities/nouns/vectors/${shard}/${id}.json`,
|
|||
|
|
`entities/nouns/metadata/${shard}/${id}.json`
|
|||
|
|
]
|
|||
|
|
})
|
|||
|
|
|
|||
|
|
// Batch delete via BlobBatchClient
|
|||
|
|
await storage.batchDelete(paths)
|
|||
|
|
|
|||
|
|
// Cost impact:
|
|||
|
|
// - Individual deletes: 1M operations × $0.0005 per 10k = $50
|
|||
|
|
// - Batch deletes: 4k batches × $0.0005 = $2 (25x cheaper!)
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### Batch Tier Changes
|
|||
|
|
|
|||
|
|
```typescript
|
|||
|
|
// Change tier for thousands of blobs efficiently
|
|||
|
|
const vectorPaths = [/* 10,000 blob paths */]
|
|||
|
|
|
|||
|
|
// Batch operation (256 blobs per batch)
|
|||
|
|
await storage.batchChangeTier(vectorPaths, 'Cool')
|
|||
|
|
|
|||
|
|
// Much faster than individual changeBlobTier() calls
|
|||
|
|
// Azure automatically batches internally for efficiency
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## Monitoring and Management
|
|||
|
|
|
|||
|
|
### Get Current Lifecycle Policy
|
|||
|
|
|
|||
|
|
```typescript
|
|||
|
|
const policy = await storage.getLifecyclePolicy()
|
|||
|
|
console.log('Active rules:', policy.rules)
|
|||
|
|
|
|||
|
|
// Example output:
|
|||
|
|
// {
|
|||
|
|
// rules: [
|
|||
|
|
// {
|
|||
|
|
// name: 'optimizeVectors',
|
|||
|
|
// enabled: true,
|
|||
|
|
// type: 'Lifecycle',
|
|||
|
|
// definition: {...}
|
|||
|
|
// }
|
|||
|
|
// ]
|
|||
|
|
// }
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### Remove Lifecycle Policy
|
|||
|
|
|
|||
|
|
```typescript
|
|||
|
|
await storage.removeLifecyclePolicy()
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### Get Storage Status
|
|||
|
|
|
|||
|
|
```typescript
|
|||
|
|
const status = await storage.getStorageStatus()
|
|||
|
|
console.log('Storage type:', status.type)
|
|||
|
|
console.log('Container:', status.details.container)
|
|||
|
|
console.log('Account:', status.details.account)
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## Azure Portal Monitoring
|
|||
|
|
|
|||
|
|
### Track Your Savings
|
|||
|
|
|
|||
|
|
1. **Storage Account** → **Insights** → View tier distribution
|
|||
|
|
2. **Cost Management** → **Cost Analysis** → Filter by storage account
|
|||
|
|
3. **Monitoring** → **Metrics** → Track blob count by tier
|
|||
|
|
4. **Lifecycle Management** → View policy execution logs
|
|||
|
|
|
|||
|
|
### Expected Metrics After 6 Months
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
Hot tier: 20-30% of total data
|
|||
|
|
Cool tier: 40-50%
|
|||
|
|
Archive tier: 20-40%
|
|||
|
|
|
|||
|
|
Monthly cost trend: Decreasing 5-8% per month as data transitions
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## Best Practices
|
|||
|
|
|
|||
|
|
1. ✅ **Use lifecycle policies** for automatic management
|
|||
|
|
2. ✅ **Archive cold data** aggressively (95% cost savings!)
|
|||
|
|
3. ✅ **Use batch operations** for tier changes and deletions
|
|||
|
|
4. ✅ **Plan rehydration** ahead of time (1-15 hour delay)
|
|||
|
|
5. ✅ **Monitor early deletion charges** (Cool: 30 days, Archive: 180 days)
|
|||
|
|
6. ✅ **Use Cool tier for infrequent access** (no rehydration needed)
|
|||
|
|
7. ✅ **Consider ZRS or GRS** for critical data redundancy
|
|||
|
|
|
|||
|
|
## Storage Redundancy Options
|
|||
|
|
|
|||
|
|
| Option | Cost Multiplier | Copies | Availability | Use Case |
|
|||
|
|
|--------|-----------------|--------|--------------|----------|
|
|||
|
|
| **LRS** | 1x | 3 (same datacenter) | 11 nines | Cost-optimized |
|
|||
|
|
| **ZRS** | 1.25x | 3 (different zones) | 12 nines | High availability |
|
|||
|
|
| **GRS** | 2x | 6 (secondary region) | 16 nines | Disaster recovery |
|
|||
|
|
| **RA-GRS** | 2.5x | 6 (read access) | 16 nines | Global read access |
|
|||
|
|
|
|||
|
|
**Recommendation for Brainy:**
|
|||
|
|
- **Production**: GRS (geo-redundancy for disaster recovery)
|
|||
|
|
- **Cost-optimized**: LRS (lowest cost, still very reliable)
|
|||
|
|
|
|||
|
|
## Troubleshooting
|
|||
|
|
|
|||
|
|
### Issue: Data not transitioning tiers
|
|||
|
|
|
|||
|
|
**Solution:**
|
|||
|
|
```typescript
|
|||
|
|
// Check lifecycle policy status
|
|||
|
|
const policy = await storage.getLifecyclePolicy()
|
|||
|
|
console.log('Policy rules:', policy.rules.map(r => ({
|
|||
|
|
name: r.name,
|
|||
|
|
enabled: r.enabled
|
|||
|
|
})))
|
|||
|
|
|
|||
|
|
// Azure lifecycle policies run once per day
|
|||
|
|
// Transitions may take 24-48 hours to execute
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### Issue: Access denied on archived blob
|
|||
|
|
|
|||
|
|
**Solution:**
|
|||
|
|
```typescript
|
|||
|
|
// Archived blobs cannot be accessed directly
|
|||
|
|
// Must rehydrate first:
|
|||
|
|
await storage.rehydrateBlob(blobPath, 'High')
|
|||
|
|
|
|||
|
|
// Wait for rehydration (check status)
|
|||
|
|
let status
|
|||
|
|
do {
|
|||
|
|
await new Promise(resolve => setTimeout(resolve, 60000)) // Wait 1 minute
|
|||
|
|
const metadata = await storage.getBlobMetadata(blobPath)
|
|||
|
|
status = metadata.archiveStatus
|
|||
|
|
} while (status && status.includes('pending'))
|
|||
|
|
|
|||
|
|
// Now access the blob
|
|||
|
|
const data = await storage.get(blobPath)
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### Issue: High early deletion charges
|
|||
|
|
|
|||
|
|
**Solution:**
|
|||
|
|
- Cool tier: 30-day minimum storage
|
|||
|
|
- Archive tier: 180-day minimum storage
|
|||
|
|
- Early deletion incurs pro-rated charges
|
|||
|
|
- Use lifecycle policies instead of manual changes to avoid early deletion fees
|
|||
|
|
|
|||
|
|
## Authentication
|
|||
|
|
|
|||
|
|
### Connection String (Simple)
|
|||
|
|
|
|||
|
|
```typescript
|
|||
|
|
const storage = new AzureBlobStorage({
|
|||
|
|
connectionString: process.env.AZURE_STORAGE_CONNECTION_STRING,
|
|||
|
|
containerName: 'brainy-data'
|
|||
|
|
})
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### Account Key (Explicit)
|
|||
|
|
|
|||
|
|
```typescript
|
|||
|
|
const storage = new AzureBlobStorage({
|
|||
|
|
accountName: process.env.AZURE_STORAGE_ACCOUNT,
|
|||
|
|
accountKey: process.env.AZURE_STORAGE_KEY,
|
|||
|
|
containerName: 'brainy-data'
|
|||
|
|
})
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### SAS Token (Granular Access)
|
|||
|
|
|
|||
|
|
```typescript
|
|||
|
|
const storage = new AzureBlobStorage({
|
|||
|
|
sasToken: process.env.AZURE_STORAGE_SAS_TOKEN,
|
|||
|
|
accountName: process.env.AZURE_STORAGE_ACCOUNT,
|
|||
|
|
containerName: 'brainy-data'
|
|||
|
|
})
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## Summary
|
|||
|
|
|
|||
|
|
**Recommended Strategy for Most Use Cases:**
|
|||
|
|
- **Lifecycle policies** for automatic tier management
|
|||
|
|
- **Batch operations** for efficient tier changes and deletions
|
|||
|
|
- **Cool tier** for infrequently accessed data (no rehydration delay)
|
|||
|
|
- **Archive tier** for long-term storage (1-15 hour rehydration)
|
|||
|
|
|
|||
|
|
**Expected Savings:**
|
|||
|
|
- **Year 1**: 40-50% reduction in storage costs
|
|||
|
|
- **Year 2+**: 60-70% reduction as more data ages into Archive
|
|||
|
|
- **Long-term**: 75-85% reduction for mature datasets
|
|||
|
|
|
|||
|
|
**500TB Example (Lifecycle Policy):**
|
|||
|
|
- Before: $112,500/year
|
|||
|
|
- After: $65,500/year
|
|||
|
|
- **Savings: $47,000/year (42%)**
|
|||
|
|
|
|||
|
|
**500TB Example (Aggressive Archival):**
|
|||
|
|
- Before: $112,500/year
|
|||
|
|
- After: $33,000/year
|
|||
|
|
- **Savings: $79,500/year (71%)**
|
|||
|
|
|
|||
|
|
**1PB Example (Lifecycle Policy):**
|
|||
|
|
- Before: $225,000/year
|
|||
|
|
- After: $131,000/year
|
|||
|
|
- **Savings: $94,000/year (42%)**
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
**Version**: v4.0.0
|
|||
|
|
**Last Updated**: 2025-10-17
|
|||
|
|
**Cloud Provider**: Azure Blob Storage
|