Ud over brugsgrænser: skalere adgang til Codex og Sora
Af Jonah Cohen, medlem af det tekniske personale
I det forgangne år har både Codex og Sora oplevet hurtig implementering, hvor brugen hurtigt har overgået vores oprindelige forventninger. Vi har observeret et konsekvent mønster: brugerne dykker ned, finder reel værdi og støder derefter på brugsgrænser.
Brugsgrænser kan bidrage til at udjævne efterspørgslen og sikre fair adgang, men når brugerne får værdi, kan det være frustrerende at blive stoppet. Vi ønskede en metode, hvor brugerne kunne fortsætte, samtidig med at vi beskyttede systemets ydeevne og brugernes tillid til vores tilgang.
For at løse det byggede vi en realtidsadgangsteknik, der tæller brug. En af funktionerne i den teknik er muligheden for at købe kreditter. Når brugere overskrider deres grænser for brug, giver kreditter dem mulighed for at fortsætte med at bruge vores produkter ved at trække på deres kreditsaldo.
Under dette ligger der et komplekst system, der kombinerer begrænsninger, sporing af forbrug i realtid og kreditbalancer i en enkelt adgangsmodel. Dette indlæg beskriver, hvorfor skalering af Codex og Sora krævede en nytænkning af adgangskontrol, hvordan et beviseligt korrekt realtidssystem kombinerer brugsgrænser og kreditter pr. anmodning, og hvordan dette fundament nu åbner op for yderligere adgang til begge produkter.
Set i et større perspektiv tvinger traditionelle adgangsmodeller ofte brugerne til at træffe et valg:
- Brugsgrænser kan være nyttige i starten, men giver brugerne en dårlig oplevelse, når de løber tør: “kom tilbage senere”
- Forbrugsbaseret fakturering er fleksibel, men betyder, at brugerne betaler fra den første token – ikke ideelt til at understøtte tidlig udforskning
For Codex og Sora var ingen af dem tilstrækkelige i sig selv. Hvis vi blot hævede grænserne for hastighed, ville vi miste vigtige mekanismer til at udjævne efterspørgslen og sikre retfærdighed, og vi ville løbe tør for kapacitet til at betjene alle. Hvis vi udelukkende baserede os på asynkron forbrugsafregning, ville vi få forsinkelser, overforbrug eller afstemningsproblemer – netop den slags problemer, som brugerne bemærker, når de er mest engagerede.
Det, vi i stedet havde brug for, var et enkelt hybridsystem, der kombinerede realtidsbegrænsninger med betal-efter-forbrug-adgang:
Dette system skulle:
- Håndhæv brugsgrænser indtil de er nået
- Overgå problemfrit til kreditter inden for den samme anmodning
- Træffe den beslutning i realtid
- Være strengt nøjagtig og kontrollerbar, når kreditforbruget spores
Et af de vigtigste konceptuelle skift, vi foretog, var at modellere adgang som en beslutningskaskade. I stedet for at spørge “er dette tilladt?”, spørger vi“hvor meget er tilladt, og hvorfra?” Når systemet tæller forbrug, går det igennem følgende sekvens:
Denne model afspejler, hvordan brugerne faktisk oplever produktet. Brugsgrænser, gratis niveauer, kreditter, kampagner og virksomhedstildelinger er alle blot lag i den samme beslutningsstak. Fra en brugers perspektiv skifter de ikke systemer – de fortsætter blot med at bruge Codex og Sora. Derfor føles kreditter usynlige: de er bare endnu et element i vandfaldet.
Vi evaluerede tredjepartsplatforme til fakturering og måling af forbrug til håndtering af kreditforbrug. De er velegnede til fakturering og rapportering, men opfyldte ikke to vigtige krav:
Når en bruger når en grænse og har kreditter til rådighed, skal systemet vide det øjeblikkeligt. Best-effort eller forsinket optælling viser sig som uventede blokeringer, inkonsistente saldi og forkerte opkrævninger. For interaktive produkter som Codex og Sora bliver disse fejl synlige og frustrerende.
Vi havde også brug for at tilbyde gennemsigtighed i hvert enkelt resultat:
- Hvorfor en forespørgsel blev tilladt eller blokeret
- Hvor meget forbrug blev der brugt
- Hvilke grænser eller balancer, der blev anvendt
Denne funktion skulle integreres tæt i vores beslutningsproces i stedet for at blive løst isoleret i en separat platform til forbrugsafregning, der kun så en del af det, der foregik. For at give brugerne adgang til vores produkter uden at gå på kompromis med tilliden, havde vi brug for fuld kontrol over korrekthed, timing og observerbarhed. Det skubbede os mod en intern løsning.
For at drive dette har vi udviklet et distribueret forbrugs- og balancesystem, der er specifikt designet til synkrone adgangsbeslutninger.
På et overordnet niveau gør systemet følgende:
- Sporer forbrug pr. bruger, pr. funktion
- Vedligeholder hastighedsbegrænsningsvinduer
- Opretholder kreditbalancer i realtid
- Debiterer saldi idempotent gennem en streaming asynkron processor
Hver anmodning gennemgår en enkelt evalueringsproces, der i realtid træffer en beslutning om, hvor meget forbrug der er tilladt, ved synkront at trække på hastighedsgrænser og, hvis nødvendigt, kontrollere, at der er tilstrækkelige kreditter. Derefter returneres et endeligt resultat, mens eventuelle kreditdebiteringer afregnes asynkront. Dette sikrer ensartet adfærd på tværs af produkter og eliminerer duplikeret logik på tværs af teams.
Et af de vigtigste designprincipper for dette system er, at vi skal kunne bevise, at vores fakturering er korrekt. Dette afspejler grundlaget for vores kreditsupport, som oprindeligt kom fra erhvervskunder. I det ovenstående systemdiagram har vi tre separate datasæt, der alle er forbundet:
- Produktforbrugsbegivenheder: Hvad brugeren faktisk gjorde
- Indtægtsgenererende hændelser: Hvad vi opkræver brugeren for deres brug
- Saldoopdateringer: Hvor meget vi har justeret brugerens kreditsaldo, og hvorfor
Disse datasæt er ikke et tilfældigt biprodukt; de driver faktisk systemet, idet hvert datasæt udløser det næste. Ved at adskille, hvad der skete, eventuelle tilknyttede gebyrer og det, vi debiterede, kan vi uafhængigt revidere, afspille og afstemme hvert lag. Dette er en bevidst afvejning, hvor vi prioriterer beviselig korrekthed, selvom det betyder, at opdateringer af kreditsaldoen bliver en smule forsinkede. Sådan opnåede vi det:
- Produktforbrugsbegivenheder offentliggøres for al brugeraktivitet, uanset om det medfører kreditforbrug eller ej. Dette giver et revisionsspor for brugeraktivitet og giver os mulighed for at forklare, hvorfor vi har trukket eller ikke trukket kreditter.
- Hver hændelse har en stabil idempotensnøgle, så genforsøg, genafspilninger eller genstarter af worker-processer aldrig kan dobbelt-debitere en saldo, hvilket forhindrer dobbeltopkrævning. Dette giver os også mulighed for at udføre en batchafstemning for at verificere vores arbejde offline.
- Vi foretager asynkrone (men stadig næsten realtids) saldoopdateringer i stedet for synkrone opdateringer for at skabe et revisionsspor. Vi tolererer en lille forsinkelse i opdateringen af brugerens saldo, så vi kan bevise, at systemet fungerer korrekt og forsikre vores brugere om, at vi ikke fejlfakturerer dem. Når den korte forsinkelse får os til at overskride en brugers kreditsaldo, refunderer vi automatisk beløbet; vi vælger beviselig korrekthed og brugertillid frem for streng håndhævelse.
- Vi reducerer Kreditsaldoen og indsætter en Saldoopdatering-post i en enkelt atomar databasetransaktion. Saldoopdateringer serialiseres pr. konto, så samtidige anmodninger aldrig kan konkurrere om at bruge de samme kreditter. Posten Saldoopdatering indeholder både debetbeløbet og en henvisning til den indtægtsgenererende hændelse, der udløste opdateringen. Ved at samle dette i en enkelt databasetransaktion sikrer vi, at vi har et revisionsspor for hver justering af kreditbalancen.
Al denne grundighed understøtter ét mål: at gøre adgang enkel og sikker. Når folk skaber eller programmerer, bør de ikke skulle bekymre sig om, hvorvidt en anmodning vil blive godkendt, om de bliver overfaktureret, eller om deres saldo er korrekt. Ved at sikre, at brug, fakturering og saldi er beviseligt korrekte, giver vi brugerne et system, der ikke forstyrrer deres oplevelse. Det er det, der gør det muligt for os at erstatte hårde stop med kontinuerlig adgang – og det er det, der gør kreditter brugbare midt i det virkelige arbejde, ikke kun på en faktura.
Det styrende princip bag vores tilgang er at beskytte brugermomentum. Hver arkitektonisk beslutning kan spores tilbage til et brugerorienteret resultat: Saldi i realtid forhindrer unødvendige afbrydelser, atomisk forbrug forhindrer dobbeltopkrævning, og ensartet adgangslogik sikrer forudsigelig adfærd. Resultatet er, at folk kan arbejde længere, udforske mere i dybden og tage projekter videre uden at opleve hårde stop eller for tidlige planændringer.
Når brugerne er engagerede, bør systemet hjælpe dem med at fortsætte og ikke stå i vejen. Grænser og kreditter forsvinder i baggrunden.
For at skabe denne oplevelse var det nødvendigt at gentænke adgang, brug og fakturering som et samlet system og opbygge en infrastruktur, der behandler korrekthed som en førsteklasses produktfunktion. Den samme platform kan med tiden udvides til flere produkter; Codex og Sora er blot begyndelsen.


