Naar de inhoud

Gidsen · Shopify · Bijgewerkt 29 september 2026 · 9 min leestijd

DeploTeka: hoe ik een platform bouwde dat per winkel één Shopify-app draait

Hoe ik DeploTeka ontwierp en bouwde om per klantwinkel een eigen Shopify-app te draaien. In productie, met de vloot van zo'n 100 winkels van Fixel Pixel.

In deze gids

·

Kort antwoord

DeploTeka is een platform dat ik heb ontworpen en gebouwd voor Shopify-app-leveranciers die elke klantwinkel een eigen app met custom distribution geven. Het claimt elke provisioningrun met een idempotentiesleutel voordat Shopify wordt aangeraakt, hervat vanaf gepersisteerde stappen, schermt verouderde workers af, houdt geheimen buiten de browser en telt een installatielink nooit als installatie. Het draait sinds juli 2026 in productie als gehoste dienst, met mijn eigen product Fixel Pixel als customer zero: een vloot van zo'n 100 Shopify-winkels.

Belangrijkste punten

  • Eén app per klantwinkel is een operationeel probleem. Het moeilijke is niet de Shopify CLI aanroepen, maar weten of een run klaar is, of hij veilig kan hervatten en of de winkel echt geïnstalleerd is.
  • Elke run wordt vóór de eerste wijziging in Shopify met een idempotentiesleutel geclaimd, doorloopt gepersisteerde stappen en hervat waar hij stopte, in plaats van een tweede, conflicterende run te starten.
  • Verouderde workers worden afgeschermd door een duurzame lease met een monotone generatie. Een effect waarvan het systeem de afloop niet kent, wordt vastgelegd als onbekend, nooit als succes.
  • De tenant zit op elke sleutel, geheimen bereiken nooit de browser, installatielinks gelden als geheim, en een winkel die DeploTeka inricht, verschijnt nooit als geïnstalleerd zonder bewijs.
  • Succes wordt gemeten aan de uitkomst, niet aan de pipeline: activatie is de eerste geslaagde Shopify-Admin-API-call met de afgeleverde credential.
Concept: afzonderlijke klantapps met een gecontroleerde releasecyclus.

Custom distribution in Shopify koppelt een app aan één winkel, of aan één Shopify Plus-organisatie. Een leverancier die aan veel onafhankelijke merchants verkoopt en elk van hen een eigen, privé-app wil geven, beheert dus één app per winkel: eerst tientallen, daarna honderden. Ik heb DeploTeka ontworpen en gebouwd om dat beheersbaar te maken. Het richt voor elke klantwinkel een eigen app in, brengt releases uit en draagt de app over, en kan op elk moment zeggen welke runs klaar zijn, welke veilig kunnen hervatten en welke winkels echt bewijs van installatie hebben. Het draait in productie als gehoste dienst, met mijn eigen meetproduct voor Shopify, Fixel Pixel, als customer zero: een vloot van zo’n 100 winkels.

De opdracht: waarom één app per winkel moeilijk is

DeploTeka is bedoeld voor Shopify-app-leveranciers: een technische oprichter met een aan Shopify gekoppeld product, of een bureau met herbruikbare app- of integratiecode, dat merchants bedient die niets met elkaar te maken hebben. Elke merchant krijgt een eigen app met custom distribution. Eén custom app delen tussen merchants die los van elkaar staan, is precies wat het product moet voorkomen.

Per winkel is het werk altijd hetzelfde. De app aanmaken. Custom distribution kiezen. De credentials in bewaring nemen en afleveren bij de backend van de leverancier. De versie van de leverancier uitbrengen. De merchant een installatielink sturen, wachten op goedkeuring, en dan uitzoeken of de juiste winkel echt de juiste installatie en versie heeft gekregen. Met de hand is dat voor elke klant dezelfde checklist, en elke stap kan op zijn eigen manier misgaan. Bij honderd winkels is de bottleneck niet meer het product, maar de operatie.

Het voor de hand liggende antwoord is een script dat de winkels langsloopt en de Shopify CLI aanroept. Dat strandt op drie vragen:

  • Is de run klaar? Provisioning is een keten: de app aanmaken, custom distribution kiezen, de credentials teruglezen, de branding toepassen, het template deployen, de ondertekende winkelspecifieke installatieovereenkomst aanmaken. Een script dat bij stap vier sterft, laat een half gebouwde app achter en geen spoor van waar het stopte.
  • Kan hij veilig hervatten? Na stap vier opnieuw beginnen is geen retry. Het is een tweede, conflicterende run tegen een live winkel.
  • Is de winkel echt geïnstalleerd? Het script ziet “installatielink aangemaakt” en meldt succes. De merchant heeft nog niets goedgekeurd.

DeploTeka bestaat om die drie vragen met bewijs te beantwoorden.

Wat ik heb gebouwd

DeploTeka is een tenant-gescheiden control plane in vier lagen: tenantbewuste contracten en beleid in het domein; orkestratie en use cases in de applicatielaag; PostgreSQL-persistentie, een versleutelde kluis en de Shopify-adapters in de infrastructuur; Fastify-routes en server-gerenderde views via HTTP. Het werkt via de officiële Shopify-API’s en CLI. De code van de leverancier blijft van de leverancier: DeploTeka leest de app-configuratie die het nodig heeft, zonder die broncode op de eigen servers te klonen, te bouwen of te draaien.

Acht onderdelen dragen het geheel.

Een tenantgrens op elke sleutel

Elke databasesleutel draagt de organisatie waartoe hij hoort, en elke repositorymethode vereist een tenant-id. Een job-id alleen geeft geen enkele toegang: wie het id van andermans run kent, kan die run niet lezen of aanraken. De isolatie zit in de datalaag, dus een nieuw scherm of endpoint kan haar niet vergeten.

Een geheimengrens op de API

De browser ontvangt nooit Partner- of Dashboard-cookies, CSRF-tokens, client secrets van de app, offline access tokens of ruwe connectorantwoorden, en niets daarvan hoort in logs of gewone statuspayloads. App-credentials worden verzegeld in een versleutelde kluis. Ook installatielinks gelden als geheim. In de webapp kan alleen een owner, admin of operator er een onthullen, elke onthulling levert een auditevent op, en op het pad voor tokenaflevering wordt bij elke onthulling een nieuwe link aangemaakt in plaats van er een op te slaan.

Idempotente, hervatbare provisioning

Een run wordt duurzaam geclaimd, met een idempotentiesleutel, vóór de eerste mutatie in Shopify. De database houdt het paar organisatie plus sleutel uniek, dus hetzelfde verzoek kan geen tweede run starten. Daarna doorloopt de run gepersisteerde stappen, elk met een eigen status, bewijs en auditevent. Heeft een stap een actie buiten DeploTeka nodig (van een operator, de merchant of een deploytool op de eigen machine van de leverancier), dan pauzeert de run op een benoemde handmatige actie en hervat hij later in dezelfde run en hetzelfde idempotentiebereik. Na een crash gaat hij verder vanaf zijn laatste gepersisteerde stap. Een effect bij de provider waarvan de uitkomst onbekend is, blijft onbekend en wordt afgestemd, nooit blind opnieuw geprobeerd.

Geversioneerde releases per winkel

De app die DeploTeka voor elke winkel genereert, is een geversioneerd asset van de tenant van de leverancier, gebouwd vanuit een template. Het control plane deployt hem, maar is niet aan zijn code gekoppeld. In de volgende release, nu in review, voegt de overdrachtsmodus een drempel toe: de installatielink voor de merchant wordt achtergehouden tot de uitgebrachte versie van de app van die winkel uit Shopify kan worden teruggelezen. Die drempel komt uit een echte run, waarin een link die was aangemaakt voordat er een versie bestond onbruikbaar bleek, terwijl de run nog steeds “gereed” meldde.

Credential-aflevering, gemeten aan de uitkomst

Credentials gaan van de kluis naar de backend van de leverancier, nooit via de browser. Elke aflevering eindigt als toegepast, herhaald of onbekend, en onbekend is geen succes en geen mislukking: het wordt afgestemd via het statuspad. Aflevering bewijst het transport, niet dat de credential werkt. Daarom betekent activatie in DeploTeka: de eerste geslaagde Shopify-Admin-API-call met de afgeleverde credential.

Die definitie heb ik vastgelegd na de eerste live credential-aflevering, op mijn eigen winkel, op 28 augustus 2026. Elk intern signaal stond op groen en de aflevering was afgerond, en toch kon de ontvangende kant geen enkele Admin-API-call doen tot iemand doorgaf welke scopes waren verleend. Een groene pipeline was geen opgelost probleem. Een werkende API-call wel.

Rollen die geheimen weghouden van status

Vier rollen. Owner: facturatie, connectorcredentials, leden, destructieve acties. Admin: templates, klanten, winkels, provisioning en leden behalve owners. Operator: klanten, winkels, provisioning en het onthullen van een installatielink. Viewer: alleen-lezen status en auditgeschiedenis, zonder links die geheimen bevatten. Een viewer kan een run van begin tot eind volgen zonder ooit de link te kunnen onthullen die de run opleverde.

Een winkel die DeploTeka inricht, telt pas als geïnstalleerd als de Shopify-authenticatie een geldige offline sessie heeft opgeleverd voor precies die winkel en dat app-client-id, en het eigendom van tenant, winkel en app in de database overeenstemt. Het ontwerp vereist ook dat de vereiste extensies van de app als gereed worden teruggelezen. In de uitgebrachte versie is die check nog voorlopig; de volgende release, nu in review, maakt hem fail closed: zonder positief bewijs antwoordt de check “onbekend”, en blijft de winkel in provisioning in plaats van als geïnstalleerd te verschijnen. Een verifier die een winkel niet kan bereiken, geeft ook “onbekend” terug, met een expliciete reden: geen vals negatief, geen stille promotie naar geïnstalleerd. Een winkel die DeploTeka inricht, verschijnt nooit als geïnstalleerd zonder bewijs.

Fencing voor verouderde workers

Elke run staat onder een duurzame lease met een eigenaar, een verloopmoment en een generatienummer dat alleen maar stijgt. Verloopt een lease en neemt een andere worker de run over, dan wordt de oude worker afgeschermd: zijn generatie is verouderd, dus hij kan de run niet meer verder brengen. Elk extern effect wordt vóór en na de call bewaakt, en een effect dat zijn lease overleeft, wordt vastgelegd als onbekend, niet als succes. De planning loopt via single-writer-lanes. De fencing is gedekt door 99 gerichte tests, waaronder twee workers die om dezelfde run strijden. Het is bewust geen exactly-once-belofte: het ontwerp maakt onzekerheid expliciet in plaats van te doen alsof ze er niet is.

Hoe het vandaag draait

De live operatie van DeploTeka doe ik zelf, met Fixel Pixel, mijn meetproduct voor Shopify, als referentie-integratie.

  • Juli 2026. Ik heb de winkelvloot van Fixel Pixel naar de productiedienst van DeploTeka gemigreerd. Die omvat nu zo’n 100 Shopify-winkels.
  • Augustus 2026. Fencing van verouderde workers afgerond, gedekt door 99 gerichte tests, gevolgd door single-writer-lanes voor de planner.
  • 28 augustus 2026. Eerste live credential-aflevering, op mijn eigen winkel.
  • 7 en 8 september 2026. Productiereleases, met op 8 september een proefrelease over twee winkels uit mijn eigen vloot.

Elke productierelease, en elke actie op een live winkel of een credential, vraagt mijn toestemming. De volgende release, nu in review, voegt de fail-closed extensiecheck en de drempel voor installatielinks toe. Hij gaat live zodra de review rond is en ik hem goedkeur.

Engineeringbeslissingen die het overnemen waard zijn

Geen ervan is specifiek voor Shopify. Ze gelden voor elk systeem dat lange jobs in meerdere stappen draait tegen API’s die je niet zelf beheert.

  1. Claim voordat je iets aanraakt. Schrijf de run en zijn idempotentiesleutel in je eigen database vóór de eerste call naar de API van een ander. Een uniciteitsconstraint op tenant plus sleutel maakt van “waren we hier al aan begonnen?” een garantie van de database.
  2. Persisteer stappen, niet alleen jobs. Een job met de status “running” zegt je na een crash niets. Een run die bestaat uit gepersisteerde stappen, elk met status en bewijs, vertelt je waar je moet hervatten, en laat een mens inspringen op een benoemde actie zonder de keten te breken.
  3. Scherm af met een generatie, niet met een timeout. Leases verlopen en trage workers worden wakker. Een monotone generatie die vóór en na elk extern effect wordt gecontroleerd, voorkomt dat een oude worker het werk van zijn opvolger overschrijft.
  4. Maak onbekend een volwaardige status. Netwerken raken antwoorden kwijt. Drie uitkomsten (klaar, mislukt, en onbekend met een reden) voorkomen dat een verloren antwoord naar groen wordt afgerond of via een retry een duplicaat oplevert. Kan een check iets niet bewijzen, laat hem dan fail closed “onbekend” antwoorden.
  5. Definieer klaar vanuit de uitkomst voor de klant. Activatie is de eerste geslaagde Admin-API-call met de afgeleverde credential, niet de laatste groene stap in je pipeline. Volgens dezelfde logica: geef nooit een link uit naar iets wat nog niet bestaat.
  6. Leg vast wat elke claim onderbouwt. Het productcontract van DeploTeka labelt elke uitspraak over het gedrag naar bewijs: code, test, gedateerd productiedocument, officiële platformbron of geaccepteerde beslissing. Zo wordt een geslaagde test niet aangehaald als bewijs van productie.

Wat er komt

Drie onderdelen: positief bewijs dat de vereiste extensies van een winkel gereed zijn, zodat die check “ja” kan zeggen in plaats van “onbekend”; een release over de hele vloot, met per winkel een vastlegging van wat er precies is uitgebracht; en de eerste externe app-leveranciers door het volledige traject leiden. Nog geen van hen heeft het afgerond.

Heb je iets vergelijkbaars nodig?

DeploTeka is het soort systeem dat ik graag bouw: veel tenants, een platform dat je niet zelf beheert, lange runs in meerdere stappen, geheimen, en de harde eis om te weten wat er werkelijk is gebeurd. Hetzelfde ontwerp werkt voor provisioningpipelines, integratieplatforms, back-office-automatisering en elke jobrunner waarin een half afgemaakte run geld kost.

Ik kan zo’n platform voor je bouwen, of het onderdeel dat je mist: idempotente provisioning, een hervatbare jobrunner, een flow voor credential-aflevering of een tenantgrens die standhoudt. Bekijk hoe ik API-integraties en automatisering aanpak, of beschrijf je taak op Task for Daniel. Wil je eerst zelf de briefing schrijven, dan zet de gids API Integration Brief (in het Engels) op een rij wat je vóór de code vastlegt, inclusief idempotentiesleutels.

Vragen die deze gids beantwoordt

Draait DeploTeka in productie?

Ja. Het draait sinds juli 2026 als gehoste productiedienst, met nieuwe productiereleases op 7 en 8 september 2026. Customer zero is mijn eigen product, Fixel Pixel: ik heb de vloot van Fixel Pixel, zo'n 100 Shopify-winkels, naar DeploTeka gemigreerd en voer de live operatie zelf uit. Nog geen externe app-leverancier heeft het volledige traject afgerond.

Wat gebeurt er als twee workers dezelfde run oppakken?

Alleen de huidige leasehouder kan de run verder brengen. Elke run staat onder een duurzame lease met een generatienummer dat alleen stijgt; verloopt een lease en neemt een andere worker over, dan is de generatie van de oude worker verouderd en wordt hij afgeschermd. Elk extern effect wordt vóór en na de call gecontroleerd, en een effect dat zijn lease overleeft, wordt als onbekend vastgelegd en afgestemd in plaats van blind opnieuw geprobeerd. De fencing is gedekt door 99 gerichte tests, waaronder twee workers die om dezelfde run strijden. Het is bewust geen exactly-once-belofte: het ontwerp maakt onzekerheid expliciet.

Wat betekent 'geïnstalleerd' in DeploTeka?

Dat de Shopify-authenticatie een geldige offline sessie heeft opgeleverd voor precies die winkel en app, en dat het eigendom van tenant, winkel en app in de database overeenstemt. Een installatielink alleen bewijst niets, want de merchant moet nog goedkeuren. Kan een check niet bewijzen dat iets gereed is, zoals de vereiste extensies van de app, dan antwoordt de volgende release 'onbekend' in plaats van 'geïnstalleerd'. Een winkel die DeploTeka inricht, verschijnt nooit als geïnstalleerd zonder bewijs.

Heeft DeploTeka iets met conversietracking te maken?

Nee. DeploTeka richt Shopify-apps in, brengt releases uit en beheert ze; het bezit niet de businesslogica van de leverancier, geen shopperdata en geen attributie. Fixel Pixel, mijn meetproduct voor Shopify, is de customer zero en referentie-integratie. Het zijn aparte producten.

Is dit een officiële Shopify-integratie?

Nee. DeploTeka is onafhankelijke software, niet verbonden aan of onderschreven door Shopify. Het gebruikt de officiële Shopify-API's en CLI. Een compatibiliteitsadapter buiten die officiële interfaces zit achter een feature flag.

Kun je zo'n platform voor mijn product bouwen?

Ja. Multi-tenant provisioning, hervatbare jobrunners, credential-aflevering en integratieplatforms met idempotentie en expliciete onbekende statussen zijn precies het werk dat ik aanneem. Beschrijf de taak op Task for Daniel, dan vertel ik hoe ik het zou aanpakken.

Bespreek je project — gratis.

Stuur één alinea: de betrokken systemen, wat er vandaag kapot is of ontbreekt, en hoe “klaar” eruitziet. Is de taak al duidelijk, dan kan ik de implementatie direct offreren. Moeten we eerst de oorzaak of de scope vaststellen, dan spreken we een apart diagnosetraject af.