Preise für Content Delivery Networks verstehen und optimieren
Eine höhere Cache-Trefferquote kann Ihre Origin-Kosten senken, während die CDN-Gebühren für Anfragen und Auslieferung fast unverändert bleiben. Trennen Sie zunächst diese Messgrößen, um CDN-Kosten zu optimieren. Prüfen Sie dann, ob Ihre Cache-Richtlinie und Bild-URLs die richtigen Bytes ausliefern, bevor Sie deren Lebensdauer erhöhen.

Was ist ein CDN?
Ein CDN empfängt Anfragen in der Nähe Ihrer Nutzer und liefert entweder eine gecachte Antwort aus oder ruft sie von Ihrem Origin ab. Ein Cache-Treffer vermeidet einen Teil der Origin-Arbeit, doch der Edge verarbeitet weiterhin die Anfrage und liefert Bytes an den Nutzer. Browser-Caching kann diese Netzwerkanfrage vollständig vermeiden; Edge-Caching kann das nicht.
Überblick über CDN-Preismodelle
Preismodelle können sich überschneiden: Ein nutzungsabhängig abgerechneter Tarif kann sowohl Anfragen als auch Transfer berechnen, mit separaten Gebühren für Compute und Sicherheit. Beginnen Sie mit Ihrer Arbeitslast und berücksichtigen Sie dann die Kontingente, Preisstufen, Regionen und Mindestabnahmeverpflichtungen des gewählten Tarifs.
| Modell | Vor der Schätzung prüfen |
|---|---|
| Monatlicher Pauschaltarif | Enthaltene Anfrage- und Transferkontingente, abgedeckter Traffic und Folgen einer Überschreitung |
| Nutzungsabhängige Auslieferung | Ausgelieferte Bytes nach Abrechnungsregion, Anfragezahlen, Freikontingente und Stufengrenzen |
| Vertrag mit Abnahmeverpflichtung | Mindestumsatz, enthaltene Produkte, Mehrverbrauch und Verfall ungenutzter Abnahmebeträge |
Stand 8. Oktober 2026 umfassen die Amazon CloudFront-Preise Pauschaltarife ohne Gebühren für Mehrverbrauch sowie eine nutzungsabhängige Abrechnung. Auch Pauschaltarife haben Nutzungskontingente. Lesen Sie die Tarifbedingungen, bevor Sie von unbegrenzter Auslieferung ausgehen. Informationen zu Paketen oder Angeboten finden Sie unter Cloudflare-Tarife, Fastly-Preise und Akamai-Preise. Falls der Link zu den Akamai-Preisen nicht verfügbar ist, finden Sie auf der Download Delivery-Seite einen Vertriebskontakt. Der niedrigste beworbene Preis eines Anbieters ist keine Schätzung für Ihre Arbeitslast.
Wichtige Einflussfaktoren für CDN-Kosten
Führen Sie vier Posten in Ihrer Kalkulation, auch wenn ein Tarif einige davon bündelt:
| Kostenposten | Daten zur Arbeitslast | Schätzung |
|---|---|---|
| Anfragen | Monatliche Nutzeranfragen nach abrechenbarer Kategorie | Abrechenbare Anfragen durch die Einheit des Preissatzes teilen und mit diesem Satz multiplizieren |
| Transfer | An Nutzer ausgelieferte Bytes nach Abrechnungsregion | Bytes in die GB-Einheit des Anbieters umrechnen, dann Kontingente und Preisstufen anwenden |
| Origin | Origin-Abrufe, übertragene Bytes und Anwendungsarbeit | Speicher-, Anfrage-, Egress- und Compute-Preissätze des Origins separat anwenden |
| Compute und Extras | Funktionsaufrufe, Dauer oder CPU-Einheiten, Transformationen, Logs und Sicherheit | Die Messgröße jedes aktivierten Produkts verwenden und nur das jeweils geltende Kontingent abziehen |
Bandbreite und Datentransfer
Ein hypothetischer Monat mit 10 Millionen Anfragen und durchschnittlich 200 KB liefert 2.000 GB aus, wobei KB und GB dezimal definiert sind. Bei erfundenen Preisen von 0,08 $/GB und 1 $/Million Anfragen sind das 160 $ für Transfer plus 10 $ für Anfragen, vor Kontingenten, Origin-Kosten, Compute, Steuern oder Abnahmeverpflichtungen. Dies sind Rechenbeispiele, keine Anbieterangebote. Verwenden Sie die tatsächlich abrechenbaren übertragenen Bytes statt unkomprimierter Dateigrößen und prüfen Sie, ob der Anbieter GB dezimal oder binär definiert.
Wenn 80 % dieser Anfragen den Edge-Cache treffen, verbleiben in einem einfachen Modell mit einem Abruf pro Cache-Fehltreffer 2 Millionen Origin-Abrufe. Das reduziert nicht die 10 Millionen Nutzeranfragen oder die 2.000 GB, die das CDN ausliefert. Revalidierung, das Zusammenfassen von Anfragen, Bereichsanfragen und unterschiedliche Objektgrößen können die Origin-Schätzung verändern. Gleichen Sie sie mit den Origin-Logs ab, statt alle Bytes mit einer Anfrage-Trefferquote zu multiplizieren.
Geografische Verteilung
Gruppieren Sie die Auslieferung nach den Abrechnungsregionen des Anbieters, nicht nach dem Standort des Origins. Sowohl die nutzungsabhängigen CloudFront-Preise als auch die Fastly-Preise haben regionale Transfertabellen. Ein regional gewichteter Durchschnittspreis benötigt Ihre Traffic-Verteilung. Ein Umzug des Origins verändert für sich genommen nicht die Messgröße für den Transfer vom Edge zum Nutzer.
Funktionsumfang und Sicherheit
Listen Sie aktivierte Produkte neben der Auslieferungsschätzung auf. WAF-Regeln, Logging, Bildoptimierung und TLS können enthalten sein, nutzungsabhängig berechnet werden oder separate Verträge erfordern. Prüfen Sie auch Gebühren auf Origin-Seite: CloudFront verzichtet derzeit auf Transfergebühren von AWS-Origins zu CloudFront, aber dadurch entfallen nicht sämtliche Gebühren für Speicher oder Anwendungsanfragen.
Edge-Computing und moderne Funktionen
Wer beliebte Bildvarianten vorab erstellt, verlagert das Encoding in einen Build oder einen Verarbeitungsjob. Das verursacht zusätzliche Speicher- und Build-Kosten. Messen Sie diese zusammen mit den Einsparungen bei der Auslieferung. Edge-Compute hat produktspezifische Messgrößen: Fastly listet Anfragen und vCPU-Millisekunden auf, während andere Produkte Aufrufe oder Dauer verwenden. Tarife können Compute enthalten. Verwenden Sie die Messgröße des gewählten Produkts.
Das folgende lokale Testprojekt prüft URL-Auswahl, Origin-Cache-Header, Komprimierung und Monitoring.
Es stellt kein CDN bereit und misst keine Cache-Trefferquote eines Anbieters. Verwenden Sie Bash,
Node.js 24.15.0 oder eine spätere gepflegte Version von Node 24
oder Node 26.5.0 oder höher aus der Versionslinie Node 26 sowie separat installiertes
Corepack und cURL. Das Beispiel nutzt das native Entfernen von
TypeScript-Typen und Dateien mit der Erweiterung .mts, um das
Modulverhalten explizit festzulegen. Yarn und die Abhängigkeiten sind unten auf feste Versionen
festgelegt. Node 24.15.0, 26.5.0 und 26.8.1 sind die getesteten Versionen, keine grundsätzlichen
API-Mindestanforderungen. Sharp erzeugt synthetische Bilder und bildet keine produktive Bildpipeline.
Fügen Sie diese Einrichtung in einem Verzeichnis ein, in dem cdn-cost-lab nicht
existiert. Die Subshell erhält das Verzeichnis und die Optionen der aufrufenden Shell, und die
Befehle brechen bei einem Fehler ab:
(
for tool in node corepack curl mkdir; do
command -v "$tool" >/dev/null || { printf 'Missing prerequisite: %s\n' "$tool" >&2; exit 1; }
done
node -e 'const [major, minor] = process.versions.node.split(".").map(Number); if (!(major === 24 && minor >= 15 || major === 26 && minor >= 5)) { console.error("Use Node 24.15+ or 26.5+ within those majors"); process.exit(1) }' &&
mkdir cdn-cost-lab && cd cdn-cost-lab &&
printf '%s\n' '{"private":true,"type":"module","packageManager":"yarn@4.12.0","dependencies":{"compression":"1.8.2","express":"5.2.1","negotiator":"1.1.0","sharp":"0.35.3"}}' > package.json &&
printf '%s\n' 'nodeLinker: node-modules' 'enableGlobalCache: false' > .yarnrc.yml &&
printf '' > yarn.lock &&
corepack yarn install
)
Falls die Installation nach dem Erstellen des Verzeichnisses fehlschlägt, behalten Sie es und
versuchen Sie es mit dem folgenden Block erneut. Erstellen Sie das Projekt darin nicht erneut.
Speichern Sie die folgenden Dateien in cdn-cost-lab.
(cd cdn-cost-lab && corepack yarn install)
Speichern Sie dies als prepare-demo.mts. Es erstellt eine transparente grüne PNG-Datei
und eine deckende rote JPEG-Datei mit demselben Basisnamen sowie deren Varianten in zwei Breiten
für jedes deklarierte Format. Die Quellerweiterung im Variantenverzeichnis verhindert, dass die
beiden Identitäten kollidieren. Das Skript weist ein vorhandenes Verzeichnis namens
dist zurück. Ein fehlgeschlagener Build kann unvollständige Ausgaben
hinterlassen. Verwenden Sie daher für einen weiteren Build ein neues Testprojekt.
import { createHash } from 'node:crypto'
import { mkdir, writeFile } from 'node:fs/promises'
import sharp from 'sharp'
await mkdir('dist')
await mkdir('dist/assets', { recursive: true })
const script = 'console.log("cdn demo")\n'.repeat(1024)
const hash = createHash('sha256').update(script).digest('hex').slice(0, 8)
await writeFile(`dist/assets/app.${hash}.js`, script)
await writeFile('dist/assets/app.js', script)
for (const [source, formats, background] of [
['logo.png', ['png', 'avif', 'webp'], { r: 0, g: 180, b: 0, alpha: 0.5 }],
['logo.jpg', ['jpeg', 'avif', 'webp'], { r: 200, g: 0, b: 0, alpha: 1 }],
]) {
for (const width of [320, 1024]) {
const directory = `dist/images/w/${width}/${source}`
await mkdir(directory, { recursive: true })
for (const format of formats) {
const extension = format === 'jpeg' ? 'jpg' : format
await sharp({ create: { width, height: width / 2, channels: 4, background } })
.toFormat(format)
.toFile(`${directory}/image.${extension}`)
}
}
}
console.log(`/assets/app.${hash}.js`)
Speichern Sie dies als variants.mts. Nur die zwei deklarierten öffentlichen Quellen
haben Varianten. Ein unbekannter Abfrageparameter führt zum Rückgabewert
null: Er könnte eine andere Version, einen Zuschnitt oder ein signiertes
Objekt auswählen. Nur w und der in diesem Testprojekt bekanntermaßen
wirkungslose Parameter utm_source dürfen entfernt werden. Erweitern Sie diese
Liste erst, nachdem Sie die Schnittstellenvereinbarungen des Origins geprüft haben. Unbekannte
Breiten verwenden 1024; doppelte Breitenparameter werden zurückgewiesen.
import Negotiator from 'negotiator'
const WIDTHS = new Map([['small', '320'], ['large', '1024']])
const PUBLISHED = new Map([
['/images/logo.png', new Map([['image/png', 'png'], ['image/avif', 'avif'], ['image/webp', 'webp']])],
['/images/logo.jpg', new Map([['image/jpeg', 'jpg'], ['image/avif', 'avif'], ['image/webp', 'webp']])],
])
export function buildVariantUrl(requestUrl, accept) {
const url = new URL(requestUrl)
const formats = PUBLISHED.get(url.pathname)
if (!formats) return null
for (const key of url.searchParams.keys()) {
if (key !== 'w' && key !== 'utm_source') return null
}
if (url.searchParams.getAll('w').length > 1) return null
// The source format wins wildcard ties; q=0 excludes a format.
const accepted = new Negotiator({ headers: { accept: accept ?? '*/*' } })
.mediaType([...formats.keys()])
const format = formats.get(accepted)
if (format === undefined) return null
const width = WIDTHS.get(url.searchParams.get('w')) ?? WIDTHS.get('large')
const name = url.pathname.slice('/images/'.length)
url.pathname = `/images/w/${width}/${name}/image.${format}`
url.search = ''
url.hash = ''
return url.toString()
}
Dies wählt eine URL aus, keinen Encoding-Vorgang. Ihr Template oder der aufrufende Code muss die
zurückgegebene URL anfordern. Ein Ergebnis von null bedeutet, dass diese
Hilfsfunktion keine sichere Variante hat. Es ist keine Erlaubnis, ein abgelehntes Format zu senden.
Ein PNG-Fallback erhält die Transparenz. Veröffentlichen Sie im Produktivbetrieb nur Varianten, die
existieren und geprüft wurden, und versionieren Sie ihre URLs bei jeder Änderung ihrer Bytes.
Die Auslieferung unterschiedlicher Formate über eine URL erfordert eine kompatible
Cache-Konfiguration. Cloudflares
Vary for Images
erfordert eine konfigurierte Variantenregel und ist in Pro, Business und Enterprise verfügbar,
aber nicht in Free. Vary: Accept allein aktiviert diese Funktion nicht.
Explizite Format-URLs trennen die Darstellungen, doch Ihr CDN muss das Caching dieser Antworten
weiterhin erlauben.
Effektives Caching implementieren
Eine Lebensdauer von einem Jahr für immutable ist nur sicher, wenn sich die URL
bei jeder Änderung der Bytes ändert. Der JavaScript-Dateiname des Testprojekts enthält einen
Inhalts-Hash. Die unversionierten Bilder bleiben eine Stunde frisch und dürfen während der
Revalidierung bis zu einem Tag lang veraltet ausgeliefert werden. Daher erreicht ein Austausch die
Clients nicht garantiert innerhalb einer Stunde. Überschreiben Sie eine URL mit Inhalts-Hash
niemals mit anderen Bytes.
Bestimmen Sie die Cache-Eignung anhand der Route, nicht der Erweiterung.
/account/avatar.jpg und /api/private.css können nutzerspezifische Daten
enthalten. Speichern Sie dies als server.mts; nur die öffentlichen Einbindungen
überschreiben die Standardrichtlinie no-store. Die Kontorouten sind
Demonstrationen ohne Authentifizierung, keine Authentifizierungsimplementierung. Das Testprojekt
bindet ausschließlich an die Loopback-Adresse.
import express from 'express'
const FINGERPRINTED = /\.[0-9a-f]{8,}\.(?:css|js|jpe?g|png|gif|webp|avif|woff2?)$/
function cacheControlFor(filePath) {
return FINGERPRINTED.test(filePath)
? 'public, max-age=31536000, immutable'
: 'public, max-age=3600, stale-while-revalidate=86400'
}
const app = express()
app.use((_req, res, next) => {
res.setHeader('Cache-Control', 'no-store')
next()
})
const publicFiles = {
setHeaders: (res, filePath) => res.setHeader('Cache-Control', cacheControlFor(filePath)),
}
app.use('/assets', express.static('dist/assets', publicFiles))
app.use('/images', express.static('dist/images', publicFiles))
app.get('/account/avatar.jpg', (_req, res) => res.type('jpg').send('per-user bytes'))
app.get('/api/private.css', (_req, res) => res.type('css').send(':root{--brand:rebeccapurple}'))
app.get('/api/failure.css', (_req, _res, next) => next(new Error('Demo failure')))
app.use((_req, res) => res.status(404).send('Not found'))
app.use((_error, _req, res, _next) => {
res.setHeader('Cache-Control', 'no-store')
res.status(500).send('Request failed')
})
const port = Number(process.env.PORT ?? 3000)
if (!Number.isInteger(port) || port < 0 || port > 65535) throw new Error('Invalid PORT')
const server = app.listen(port, '127.0.0.1', (error) => {
if (error) {
console.error(`Listen failed: ${error.code}`)
process.exitCode = 1
return
}
console.log(`http://127.0.0.1:${server.address().port}`)
})
process.once('SIGINT', () => server.close())
process.once('SIGTERM', () => server.close())
Erstellen Sie innerhalb von cdn-cost-lab die Fixtures und starten Sie den Origin.
PORT=0 wählt einen ungenutzten Port. Kopieren Sie die ausgegebene Origin-URL
für das nächste Terminal. Stoppen Sie den Server im Vordergrund mit Ctrl+C.
node prepare-demo.mts && PORT=0 node server.mts
Setzen Sie in einem zweiten Terminal innerhalb des Testprojekts DEMO_ORIGIN auf
diese ausgegebene URL. Führen Sie dieses Gegenstück aus, um eine kleine WebP-Variante auszuwählen
und abzurufen. Die PNG-Quelle und die Breite bleiben in ihrem Pfad erhalten:
DEMO_ORIGIN='http://127.0.0.1:REPLACE_WITH_PRINTED_PORT'
node --input-type=module - "$DEMO_ORIGIN" <<'NODE'
import { buildVariantUrl } from './variants.mts'
const url = buildVariantUrl(`${process.argv[2]}/images/logo.png?w=small`, 'image/webp')
if (url === null) throw new Error('No acceptable variant')
const response = await fetch(url)
if (!response.ok) throw new Error(`HTTP ${response.status}`)
const bytes = new Uint8Array(await response.arrayBuffer())
console.log(new URL(url).pathname, response.headers.get('content-type'), bytes.length)
NODE
Erwarten Sie /images/w/320/logo.png/image.webp, image/webp und eine positive
Byteanzahl. Das belegt, dass das ausgewählte Objekt erreichbar ist. Prüfen Sie seine Pixel, wenn
Sie diese Demo durch Ihren eigenen Build ersetzen. Fordern Sie den vom Build ausgegebenen
Asset-Pfad mit Hash an, um immutable zu prüfen. Diese Befehle zeigen die
Richtlinien für unversionierte, private und fehlende Objekte. Verwenden Sie denselben Wert für
DEMO_ORIGIN:
curl -fsSI "$DEMO_ORIGIN/assets/app.js" &&
curl -fsSI "$DEMO_ORIGIN/account/avatar.jpg" &&
curl -sSI "$DEMO_ORIGIN/assets/absent.js"
Die erste Antwort hat max-age=3600, stale-while-revalidate=86400; die zweite und die 404-Antwort haben
no-store. Diese Origin-Header belegen nicht, dass ein bereitgestelltes CDN
sie berücksichtigt. Prüfen Sie seine Cache-Regeln, Cookies, den Umgang mit Autorisierung und
Cache-Status-Logs, bevor Sie gemeinsames Caching aktivieren.
Performance überwachen und optimieren
Eine brauchbare Messabfrage muss Antworten außerhalb des 2xx-Bereichs zurückweisen, den gesamten
Antwortkörper lesen und die Dauer der vollständigen Anfrage begrenzen. Speichern Sie dies als
edge-monitor.mts. Es wartet zwischen aufeinanderfolgenden Messungen fünf Minuten und
bricht bei Ctrl+C einen aktiven Abruf oder einen laufenden Warte-Timer ab. Das Zeitlimit von fünf
Sekunden umfasst die Übertragung des Antwortkörpers. Daher kann ein großes Asset bei langsamer
Verbindung trotz Fortschritt fehlschlagen.
import { setTimeout as sleep } from 'node:timers/promises'
async function probeEdge(url, timeoutMs = 5000, signal) {
const start = performance.now()
const deadline = AbortSignal.timeout(timeoutMs)
const response = await fetch(url, {
signal: signal ? AbortSignal.any([signal, deadline]) : deadline,
})
try {
if (!response.ok) return { url, ok: false, status: response.status }
let bytes = 0
if (response.body) {
for await (const chunk of response.body) bytes += chunk.byteLength
}
return {
url, ok: true, status: response.status, bytes,
duration: performance.now() - start,
cache: response.headers.get('cf-cache-status') ?? 'unknown',
}
} finally {
if (!response.bodyUsed) await response.body?.cancel()
}
}
function formatProbe(result) {
const { origin, pathname } = new URL(result.url)
if (!result.ok) return `${origin}${pathname} FAIL ${result.error ?? `HTTP ${result.status}`}`
return `${origin}${pathname} ${result.status} ${result.duration.toFixed(0)}ms ${result.bytes}B cache:${result.cache}`
}
async function monitorEdge(url, signal, intervalMs = 300_000) {
while (!signal.aborted) {
const result = await probeEdge(url, 5000, signal)
.catch((error) => ({ url, ok: false, error: error.name }))
if (signal.aborted) break
console.log(formatProbe(result))
await sleep(intervalMs, undefined, { signal }).catch((error) => {
if (error.name !== 'AbortError') throw error
})
}
}
const url = process.argv[2]
if (!url) throw new Error('Usage: node edge-monitor.mts URL')
const controller = new AbortController()
process.once('SIGINT', () => controller.abort())
process.once('SIGTERM', () => controller.abort())
await monitorEdge(url, controller.signal)
Führen Sie node edge-monitor.mts "$DEMO_ORIGIN/assets/app.js" aus. Eine erfolgreiche Zeile enthält HTTP 200, die
verstrichenen Millisekunden, Bytes und cache:unknown für diesen lokalen Origin.
Abfrageparameter werden in den Logs ausgelassen, weil URLs signierte Tokens enthalten können.
Die Messabfrage misst den Übertragungsweg eines Prozesses, keine Nutzerlatenz oder globale
Cache-Trefferquote. Die Fetch-Funktion von Node decodiert komprimierte Antwortkörper. Daher
entspricht diese Byteanzahl nicht den komprimiert übertragenen Bytes oder einer Messgröße für
die Abrechnung. Der Header cf-cache-status ist Cloudflare-spezifisch. Passen Sie ihn
an Ihren Anbieter an. Jede Messabfrage erzeugt Traffic, der bei Anfragen und Transfer zählen kann.
Strategien zur Optimierung der CDN-Kosten
Wählen Sie die Änderung anhand Ihrer Kalkulation: Kleinere Darstellungen reduzieren die ausgelieferten Bytes, Edge-Caching reduziert Origin-Arbeit, und Browser-Caching reduziert wiederholte Netzwerkanfragen. Prüfen Sie eine Änderung anhand der zugehörigen Messgröße, statt anzunehmen, dass alle vier Kostenposten gemeinsam sinken.
Unnötige Datentransfers minimieren
Um die Origin-Komprimierung zu testen, fügen Sie dies in server.mts direkt nach
const app = express() ein und starten Sie den Server anschließend mit
PORT=0 node server.mts neu. Der Import bleibt auf Modulebene. Dies ist eine Ausweichlösung,
wenn die Komprimierung nicht bereits an anderer Stelle Ihres Auslieferungswegs erfolgt.
import compression from 'compression'
app.use(compression({ level: 6, threshold: 0 }))
Fordern Sie /assets/app.js mit Accept-Encoding: gzip an und prüfen Sie
Content-Encoding, die Byteanzahl des komprimierten Antwortkörpers und die decodierten
Bytes im Vergleich zum Original. Speichern Sie dies als check-compression.mts und führen
Sie node check-compression.mts "$DEMO_ORIGIN" aus, nachdem Sie DEMO_ORIGIN auf die
vom neu gestarteten Server ausgegebene URL gesetzt haben. Es liest rohe HTTP-Bytes, weil die
Fetch-Funktion sie für Sie decodieren würde:
import { strict as assert } from 'node:assert'
import { readFile } from 'node:fs/promises'
import { get } from 'node:http'
import { gunzipSync } from 'node:zlib'
const url = new URL('/assets/app.js', process.argv[2])
const response = await new Promise((resolve, reject) => {
get(url, { headers: { 'Accept-Encoding': 'gzip' }, signal: AbortSignal.timeout(5000) }, resolve)
.on('error', reject)
})
const chunks = []
for await (const chunk of response) chunks.push(chunk)
assert.equal(response.statusCode, 200)
assert.equal(response.headers['content-encoding'], 'gzip')
const encoded = Buffer.concat(chunks)
const original = await readFile('dist/assets/app.js')
assert.equal(Buffer.compare(gunzipSync(encoded), original), 0, 'Decoded bytes differ from the source')
console.log(`${encoded.length}B gzip, ${original.length}B decoded`)
Komprimieren Sie JPEG, WebP oder AVIF nicht erneut mit gzip, nur weil sie groß sind. Die
Komprimierungs-Middleware filtert nach Inhaltstyp und
berücksichtigt no-transform. Die Komprimierungskonfiguration Ihres CDNs kann
abweichen. Dieses Testprojekt belegt keine Komprimierungseinsparungen für Ihre produktiven Assets.
Caching effektiv nutzen
Normalisieren Sie nur Abfrageparameter, die nachweislich für das Objekt irrelevant sind.
Hier wird w=small zu einem Pfadsegment, und utm_source
kann verworfen werden. Für version, crop und
signierte Tokens gilt das nicht. Die Hilfsfunktion weist diese unbekannten Eingaben zurück, statt
sie einem anderen Objekt zuzuordnen. Erfassen Sie Anfrage-Trefferquote und Byte-Trefferquote
getrennt. Prüfen Sie, welche Varianten oder Abfragewerte zu Cache-Fehltreffern führen, bevor Sie
den Cache-Schlüssel ändern.
Fazit
Wenden Sie die gewählte Preisliste auf die Anfrage-, Regions-, Transfer- und Origin-Daten eines Monats an. Vergleichen Sie dann eine weitere Schätzung nach Ihrer gemessenen Änderung. Falls Ihre Anwendung während des Builds einen Schritt zur Dateiverarbeitung benötigt, kann Transloadit diesen Teil des Workflows übernehmen. Cache-Richtlinien und Anbieterabrechnung erfordern weiterhin eigene Prüfungen.
