agentsclimarketplace

Optimizing azure blob storage cost

Skill alexpizarro/azure-lean-stack-skills/skills/optimizing-azure-blob-storage-cost

Configures Azure Blob Storage with lifecycle rules that auto-delete stale temp blobs and tier production data through Hot → Cool → Cold without rehydration latency. Provides CORS rules tuned for SPA + SAS uploads/Range reads, public-read branding container alongside private app containers, and SKU/redundancy guidance to keep cost minimal. Use when adding blob storage for uploads, designing storage for a media-heavy app, or auditing an existing storage account for cost waste.From its SKILL.md

Install
npx -y skills add alexpizarro/azure-lean-stack-skills --skill optimizing-azure-blob-storage-cost

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

One thing to look at

  • 1 stars1 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.

SKILL.md

6.4 KB, ~1.4k tokens by cl100k_base, as published. Nobody here has run it

Optimizing Azure Blob Storage Cost

Default-low-cost blob storage with lifecycle rules tuned for media workloads (and any pattern with ephemeral temp blobs + long-lived primary blobs).

When to invoke

  • Adding a blob storage account to a project
  • Designing for uploads (SAS-based) + serving (Range / CORS)
  • Auditing an existing storage account that's growing unbounded
  • A project that stores media (video, large images, archives) where retention > 60 days

The two-pattern playbook

Pattern A: temp + permanent containers

Most apps have two flavours of blob:

  • Temp — short-lived working data (uploads being processed, intermediate transformations, cache)
  • Permanent — user-visible content (videos, images, exports)

Apply different lifecycle rules to each:

resource tempBlobLifecycle 'Microsoft.Storage/storageAccounts/managementPolicies@2023-05-01' = {
  parent: storageAccount
  name: 'default'
  properties: {
    policy: {
      rules: [
        // Rule 1: delete stale temp blobs after 7 days
        {
          enabled: true
          name: 'delete-stale-temp-blobs'
          type: 'Lifecycle'
          definition: {
            filters: {
              blobTypes: ['blockBlob']
              prefixMatch: ['incoming/', 'processor-jobs/', 'tmp/']
            }
            actions: {
              baseBlob: { delete: { daysAfterModificationGreaterThan: 7 } }
            }
          }
        }
        // Rule 2: age permanent blobs through tiers — NEVER use Archive for
        // playable/viewable content (rehydration takes hours)
        {
          enabled: true
          name: 'tier-aging-content'
          type: 'Lifecycle'
          definition: {
            filters: {
              blobTypes: ['blockBlob']
              prefixMatch: ['videos/', 'images/', 'exports/']
            }
            actions: {
              baseBlob: {
                tierToCool: { daysAfterModificationGreaterThan: 60 }
                tierToCold: { daysAfterModificationGreaterThan: 180 }
                // intentionally NO tierToArchive — needs rehydration
              }
            }
          }
        }
      ]
    }
  }
}

See references/lifecycle-rules.md.

Pattern B: per-container public/private

Most containers stay private (publicAccess: 'None') with SAS-based access. One opt-in public-read container for assets that need to be served via plain URLs (branding, public catalog images):

resource brandingContainer 'Microsoft.Storage/storageAccounts/blobServices/containers@2023-05-01' = {
  parent: blobService
  name: 'branding'
  properties: { publicAccess: 'Blob' }    // read-only public access
}

To allow this, the storage account itself must set allowBlobPublicAccess: true. Other containers remain publicAccess: 'None' — that's the explicit per-container setting.

Storage account defaults

resource storageAccount 'Microsoft.Storage/storageAccounts@2023-05-01' = {
  kind: 'StorageV2'
  sku: { name: 'Standard_LRS' }            // LRS = cheapest. Use GRS only when DR matters.
  properties: {
    accessTier: 'Hot'                      // Hot for new blobs (lifecycle ages them later)
    supportsHttpsTrafficOnly: true
    minimumTlsVersion: 'TLS1_2'
    allowBlobPublicAccess: true            // gated per-container; flip to false if no public container exists
  }
}
SettingDefaultWhen to change
sku.nameStandard_LRSStandard_GRS for geo-redundant backups (~2× cost)
accessTierHotSet Cool at account level if 95%+ of writes are write-once-read-rarely
allowBlobPublicAccesstrue only if a public container existsfalse otherwise — defence in depth

See references/access-tiers.md.

CORS for SPA + SAS

Browser uploads via SAS and Range reads (e.g. video players with crossOrigin="anonymous") need CORS:

resource blobService 'Microsoft.Storage/storageAccounts/blobServices@2023-05-01' = {
  parent: storageAccount
  name: 'default'
  properties: {
    cors: {
      corsRules: [
        {
          allowedOrigins: [
            'https://app.example.com'
            'http://localhost:5173'
          ]
          allowedMethods: ['GET', 'PUT', 'OPTIONS']
          allowedHeaders: ['*']
          exposedHeaders: ['*']                    // required for Range responses
          maxAgeInSeconds: 3600
        }
      ]
    }
  }
}

See references/cors-for-spa.md.

The Archive trap

Do not use tierToArchive in lifecycle rules for content that needs to stay playable. Archive tier requires manual rehydration that takes 1–15 hours and bills extra. Symptoms:

  • Video plays fine for 90 days, then suddenly returns 409 Conflict
  • Image URLs return RehydrationRequired errors
  • Customer support tickets that take hours to resolve

Use Cold instead (~$0.0036/GB/month). Cold is still online and instantly accessible.

Storage naming

Storage account names must be lowercase, alphanumeric, ≤24 chars:

{org}{project}store{env}     e.g. acmetaskappstoretest

If the resulting name exceeds 24 chars, shorten project or drop the store suffix.

Composes with

Templates

FilePurpose
templates/storageAccount-with-lifecycle.bicepStorageV2 + lifecycle + CORS + private/public containers

What ships with it: 4 files

14.3 KB alongside SKILL.md

Keep looking

Skills are one crate of 623,467. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.