Insights

  • DAM for developers: the API-first path

    DAM for developers: the API-first path

    The evaluation document has forty rows and thirty-six of them are about the interface. You will use the interface twice. You will use the API every day for the next four years.

    Short answer: an asset platform is worth adopting when three things are true. You can upload and get back a stable identifier in one call, you can construct any rendition as a URL without a round trip, and you can search and manage assets over a documented API with real SDKs. Everything else is convenience. Those three determine whether it disappears into your stack or becomes a system you maintain.

    The three primitives

    Upload returns an identifier. One call, a file or a remote URL in, a stable identifier out. The identifier must be yours to choose or at least yours to predict, because your product records will store it and they will be written before the upload completes in at least one code path. Upload presets are the mechanism for making an upload carry a policy rather than a pile of parameters, which matters as soon as more than one thing uploads.

    Renditions are URLs. Given an identifier and a set of parameters, the delivery URL is constructible client-side, deterministically, with no API call. This is the property that makes the whole thing composable, and it is what separates a delivery platform from a file host with a resize endpoint. The transformation reference is worth reading not to memorise but to check that the parameter space covers what your design system needs.

    Assets are queryable. Not just listable. A search API that can filter on your own structured fields is the difference between an asset library and a bucket with a nice front end, and it is the thing you will need the first time someone asks for every image using an expiring licence.

    If a platform gives you those three cleanly, most integration questions have short answers. If it gives you two, you will be writing a service to paper over the third.

    The first call test

    Before any evaluation meeting, try to get from nothing to a working delivery URL. Time it, and note how many browser tabs you needed.

    The shape you want looks roughly like this: install the SDK, set one credential, upload a file, receive an identifier, print a URL with a size and a format parameter, load it in a browser. Cloudinary publishes SDKs across about seventeen languages plus a CLI, and the whole loop is a handful of lines in any of them.

    That test tells you more than a feature matrix, for a reason worth stating explicitly. The path from zero to a working call is the path every developer on your team will take, repeatedly, for years, and the path an AI coding assistant will take when it writes the integration for you. A platform whose first call requires provisioning, a support conversation and a bucket policy is a platform that will be integrated once, badly, by whoever drew the short straw.

    Cloudinary has done unusual work on that second audience specifically. It ships MCP servers and an llms.txt alongside the normal documentation, so an assistant retrieving context gets the real parameter syntax rather than a plausible guess. Whether or not you care about that today, it is a reasonable proxy for how seriously a vendor takes the machine-readable surface of its own product.

    Why day one beats month eighteen

    This is the part that gets argued about, so here is the argument without adjectives.

    The usual advice is that a media platform is something you adopt once you have a scale problem. That advice assumes the value is scale-contingent, and it is not. What you get from the first upload is structure: the asset has an identifier, a description, a version, and a defined way to render itself. What you get without it is a file in a folder whose meaning lives in a naming convention and in the head of whoever wrote it.

    The cost of not having that structure shows up immediately, not at scale:

    • The first crop someone needs becomes a file. By month three there are two hundred files nobody can trace to a master.
    • Image paths get hard-coded into the front end, because there is nothing to construct them from.
    • Nothing records what an image depicts, so alt text is either absent or invented per placement.
    • Nobody can tell which of two similar files is current, at forty assets just as much as at forty thousand.

    Then the migration arrives. Moving to a structured media layer at month eighteen means finding every hard-coded path across every codebase, matching every stored derivative to a master that may no longer exist, and backfilling metadata that was never captured. Doing it on day one costs an account and a URL helper.

    For a solo developer or a small team building an MVP, this is the whole argument. You are not adopting infrastructure for the scale you hope to reach. You are avoiding a migration you would otherwise schedule for the exact quarter when you can least afford it. The free Programmable Media tier makes the day-one version cost nothing, which removes the last reason to defer.

    A teal-edged core with six radial connector plugs, five seated and one amber plug held at an angle with the wrong key profile

    What to check that the demo will not show you

    Signed and time-limited URLs. If any asset is not public, you need signed delivery and you need to understand how signature verification interacts with caching. Ask early, because retrofitting it is unpleasant.

    Access control granularity. Be precise here, because vendor material tends not to be. Permissions in most asset platforms, Cloudinary included, are organised at the folder level rather than per asset. That is usually fine, and it is only fine if you design your structure around it rather than assuming per-asset rules you can query at runtime.

    Relationships between assets. Similarly, do not design an integration that depends on traversing arbitrary asset-to-asset relationships as a first-class API concept. Model relationships on the product side, where they belong anyway, as described in DAM vs PIM.

    Eventing. Notifications on upload, transformation and moderation, with retries and signed payloads, so your systems react rather than poll.

    Exit. Can you enumerate every asset and download every master through the API. The answer sets your migration cost, in both directions, and migration tooling that works on the way in usually works on the way out.

    Four teal cards in a short vertical sequence beside a much longer column of fourteen small amber cards descending past the frame edge

    When is a bucket and a CDN enough?

    When all of the following hold, and they hold more often than this page implies.

    • Assets are public, few, and rarely change.
    • One front end, one set of breakpoints, no marketplace or partner consuming your images.
    • No third-party rights and no expiry dates to track.
    • Nobody needs to search assets by anything other than filename.

    That is a real configuration and object storage behind a CDN serves it well. The threshold is crossed by the second consumer of the same images, or by the first licence that expires, and both tend to arrive without warning.

    What is worth avoiding either way is the middle option: a bucket, plus a resizing service, plus a hand-rolled metadata table. That combination has the operational burden of a platform and the capability of a folder, and the reasoning behind that judgement is in build versus buy for the product catalogue.

    What does the integration look like once it is right?

    Small. The product record holds an identifier. A shared helper turns an identifier plus a named shape into a URL. The front ends call the helper. A webhook updates a three-field read model when an asset changes state. There is no sync job and no staging directory.

    That is the whole thing, and the surrounding design is in wiring a DAM to a PIM for the catalogue side and media in a headless commerce stack for the front-end side. The asset-level capabilities it depends on are in what a DAM actually does, and the parallel set of questions for the product platform is in what to demand from a PIM API before you buy. If you are weighing this against assembling something from tools you already have, alternatives to buying a DAM and a PIM covers those honestly.

  • Build versus buy for the product catalogue

    Build versus buy for the product catalogue

    An engineering team looks at a product platform quote, looks at the feature list, and concludes correctly that they could build eighty per cent of it in a quarter. They are right. The trouble is the shape of the remaining twenty per cent, which is not eighty per cent smaller.

    Short answer: building a product catalogue is defensible when your model is unusual and your channel count is low, and it is a permanent commitment rather than a quarter. Building a media delivery layer is almost never worth it, because the hard parts are format negotiation, caching and edge delivery, all of which are commodity and none of which are your product. Split the two decisions.

    What you are actually buying

    Strip the marketing and a product platform sells four things.

    A modelling engine that can express families, products, variants, typed attributes and localised values, and enforce them. This is the part teams underestimate, because a first version is easy and the fifth revision is not.

    A completeness engine that scores records against per-channel rule sets and blocks publication. This is the part that pays for itself.

    A workflow layer with roles, states and assignment. This is the part most teams already have somewhere else and often do not need twice.

    Channel mappings to marketplaces and retailers, maintained by someone else as those specifications change. This is the part with no ceiling, because the specifications change without asking you.

    You can build the first three. The fourth is a subscription to someone else’s maintenance burden, and it is often the honest reason to buy.

    The build case, stated fairly

    There are real conditions under which building is correct.

    Your model is genuinely unusual. Configurable products, made-to-order dimensions, service bundles, regulated goods with jurisdiction-specific field sets. If every platform demo ends with “we would handle that with a custom field”, building is worth costing properly, because a platform you have to fight is worse than no platform.

    You have one or two channels and no plans for more. The channel mapping burden is what makes building expensive over time, and if you only ever publish to your own storefront, that burden is small and stable.

    Product data is your product. Marketplaces, aggregators and comparison sites are in this position. Buying a generic catalogue to run a catalogue business is odd.

    You have engineering capacity that is not otherwise committed. Not “we could find the time”. Committed capacity, permanently, because this becomes a system with an on-call rota.

    If two or more of those are true, build is a real option. If none is, the discussion is usually about wanting to build rather than about needing to.

    What the maintenance actually costs

    The build estimate is nearly always for version one and the cost is nearly all after it.

    • Schema evolution. Every new attribute type, every new market, every change to what localisable means. Small individually, continuous forever.
    • Channel specification drift. Every marketplace changes its requirements at least annually, sometimes silently. Each change is a mapping update and a validation update, discovered through rejections.
    • Import and export tooling. Suppliers send spreadsheets in whatever shape they like. Ingestion is a long tail that never ends.
    • The interface. Cataloguers need one, and it is not a weekend project. This is the single most underestimated line in every build estimate.
    • Concurrency and audit. Who changed what, when, and what did it look like before. Easy to skip in version one and painful to retrofit.

    Cost the second and third years, not the first. A build that flattens after eighteen months is a good build; most do not flatten, and the curve to compare against is the total cost of ownership of the alternative rather than its licence line, as set out in what a DAM and a PIM actually cost.

    A central card ringed by three dashed circles holding six teal blocks, nine pale blocks and fourteen amber blocks spilling past the outer ring

    The media layer is a different decision

    Here the answer is much less balanced, and it is worth being direct about why.

    Building a media layer means owning storage, format negotiation, resizing quality, caching, invalidation and edge delivery. Each of those is a solved commodity problem with a long tail of correctness issues, and none of them differentiates your business.

    Format negotiation alone is a good example. Serving AVIF or WebP to browsers that support them and JPEG to those that do not, with correct Accept handling and cache keys that do not collide, is more subtle than it looks and has to be revisited as format support changes. Getting it slightly wrong produces either broken images for some users or a cache that serves the wrong format to the wrong browser, which is a bug that reproduces for nobody on the team.

    The realistic build here is object storage plus a resizing service plus a CDN, which is three moving parts, an ongoing cost, and no metadata layer at all. That last omission is the important one: you have built delivery, not asset management. Nothing in it knows what an asset depicts, what is permitted, or which version is current.

    The managed alternative starts free and stays cheap at small scale. Cloudinary’s Programmable Media free tier is 25 credits a month, where a credit is 1,000 transformations, 1 GB of storage or 1 GB of delivery. For a small catalogue that is not a trial, it is the whole requirement, and it comes with the structured metadata layer that the build-it-yourself version does not have.

    The case for adopting it on day one rather than after you have built the three-part version is simply that the migration is the expensive part. Starting with a master and a URL costs nothing and gives you the structure from the first upload. Arriving at it eighteen months later means finding every stored derivative and every hard-coded path in every codebase, which is the argument made in full in DAM for developers.

    Macro of a stack of printed sheets along the cut edge, orderly for two thirds and fanning into dog-eared amber sheets at the top

    The middle path most teams should take

    Buy the media layer, build the thin catalogue, and keep the option open.

    Concretely: put assets on a managed delivery platform immediately. Keep product data in whatever you have, modelled properly, with typed attributes and a real variant structure. Write the channel mappings as small, declarative, testable code rather than as a platform configuration. That combination costs almost nothing, and it produces a data model that can be loaded into a bought platform later without a cleanup pass, which is the expensive half of any migration.

    The decision point comes when the channel mapping work starts consuming a person. That is the moment the subscription to someone else’s maintenance burden starts looking cheap, and it is a much clearer signal than any threshold based on catalogue size.

    How do you decide this week?

    Score four questions honestly. Is the model unusual, is the channel count above two, is engineering capacity actually committed, and is product data your product. Two or more yeses point to build, and fewer than two point to buy.

    Then apply the same four questions to the media layer separately, and notice that the answers are almost always different. If they are not, one of the answers is probably wishful.

    The threshold test for whether you need a bought catalogue at all is in do you need a PIM yet, the API questions that determine whether a bought one will integrate cleanly are in what to demand from a PIM API before you buy, and the lighter-weight options that are neither building nor buying are in alternatives to buying a DAM and a PIM.

    Related field note

    Continue with The build-versus-buy decision for ERP product identifiers.

    Related field note

    Continue with The build-versus-buy decision for catalog launch readiness.

  • Product photography without a studio backlog

    Product photography without a studio backlog

    A studio can shoot a lot of products in a day. Almost none of them reach a product page that week. The gap is where the backlog lives, and it is mostly not photography.

    Short answer: three things create studio backlogs. Setups that are rebuilt from memory each session, so images do not match between batches. Shot lists that are agreed after the shoot, so frames are missing and products come back. And a post-production step whose main output is crops, which should not be produced at all. Fix those and throughput roughly doubles without a second studio.

    Standardise the setup, then never rebuild it

    Consistency across a product grid matters more than the quality of any single frame. A customer scrolling a category page reads inconsistency instantly and quality barely at all.

    The way to get consistency is to stop treating the setup as a creative decision each time.

    • Fix the camera position, lens, height and distance per category. Write them down with numbers, not adjectives. Mark the floor.
    • Fix the lighting. Same modifiers, same positions, same power. Photograph the setup itself and pin the photograph up.
    • Shoot a reference target at the start of every session. A grey card and a colour checker take ten seconds and make colour correction deterministic instead of subjective.
    • Keep a physical reference product. Shoot it first each session and compare against the last session’s frame. If they do not match, something moved, and you want to know before three hundred products go through.

    The gain is not only visual. A standardised setup means the crop and the framing are predictable, which means downstream processing can be automated instead of eyeballed.

    Agree the shot list before the sample arrives

    Reshoots are the most expensive failure in the pipeline because they consume a slot, a sample and a second round of everything after.

    The shot list should be a property of the category, not of the shoot. Every chair gets these seven angles. Every garment gets these five plus a detail. Written once, reused every season, and known to the person booking samples so that a product without the required angles never leaves the studio.

    Two additions make it much more useful. First, mark which frames are mandatory for each channel, so the studio knows the square-on-white is not optional if you sell on a marketplace that requires it. Second, treat the list as a manifest for ingest, so the pipeline can tell you which frames are missing rather than someone noticing later. That is the same manifest idea described in the product image workflow.

    Macro of colour checker patches under raking teal light, five reading as a consistent sequence and the sixth amber and out of sequence

    Stop making crops

    Look at what post-production actually spends its time on. A share of it is real work: cleanup, colour, background, product accuracy. The rest is producing the six or eight sizes and aspect ratios that different destinations need.

    That second part should not exist. If renditions are derived from an approved master by parameter, the studio ships one file per frame and the destinations take the shapes they need. This removes a step, removes a storage problem, and removes the whole class of bug where the product page updates and the marketplace listing keeps the old crop.

    Two mechanics make it work reliably at scale.

    Content-aware cropping. A centre crop of a wide product shot cuts the product in half. Automatic subject-aware cropping, such as gravity-based cropping, gets it right for most frames without a person choosing a focal point. Set a focal point manually for the exceptions.

    Background handling as a transformation. Cutting out a product against white is genuine post-production work, but a large share of it is now doable as a transformation on delivery rather than as a file someone produces. Treat it as a first pass to be reviewed rather than as a finished result, and keep the master untouched underneath.

    The point is not that the tooling is clever. It is that the studio’s output becomes one master per frame, which is the smallest thing it can be, and everything downstream is a parameter.

    Add capacity without adding a studio

    When the shoot slot genuinely is the bottleneck, the options are cheaper than a second studio.

    Batch by setup, not by product. Shooting every product that uses the same setup consecutively removes the rebuild time between products, which is often more than the shooting time. This can double throughput on its own and it costs nothing.

    Shoot in a fixed rhythm. A standing weekly session that always happens is more productive than an ad hoc session that gets scheduled around availability, because samples can be prepared against a known date.

    Separate the easy from the hard. Most catalogues are eighty per cent products that need seven standard frames and twenty per cent that need art direction. Running them through the same process paces everything at the speed of the hard ones. Split the flow.

    Consider a second location for the standard eighty per cent. A fixed, standardised setup can be replicated. An art-directed one cannot. This is the argument for outsourcing the simple flow rather than the complex one, which is the opposite of what usually happens.

    A three by four grid of framing templates with teal crop guides, ten centred and two amber with the subject offset and clipped

    Preserve metadata through post-production

    Every export step is an opportunity to lose the information that makes the images findable later.

    Capture software can write the SKU, the shoot date, the photographer and the campaign into the file at capture. Retouching software can strip all of it on export, and often does, depending on the export preset. IPTC photo metadata fields are the standard carrier for this, and ExifTool is how you check whether yours survived a round trip.

    Test your own pipeline once, deliberately: write known values at capture, run a file through the whole post-production path, and read them back at the end. Whatever is missing is missing for every image you have ever shipped, and the fix is usually one export preset.

    What does good throughput look like?

    Ranges rather than targets, because category matters enormously. A standardised tabletop setup with a fixed shot list will comfortably do thirty to sixty products a day with one photographer and one assistant, where a product means seven frames. Art-directed lifestyle work is a different activity and comparing them is not useful.

    What is worth comparing is your own before and after. Measure products published per week, not frames captured, because frames captured is the number that looks good while the backlog grows. The operating model that keeps that number stable across a season is in running product content as an operation, and the pre-launch version is in the catalogue launch checklist. For what the images should carry once they land in the library, see what a DAM actually does.

  • The PIM API: what to demand before you buy

    The PIM API: what to demand before you buy

    The API section of the demo lasts four minutes. Someone fetches a product, the JSON looks reasonable, everyone nods. Six months later you are writing a script that pages through eleven thousand products every night because there is no way to ask what changed.

    The four minutes were not enough. Here is what to ask instead.

    Short answer: eight questions decide whether an integration will be pleasant or permanent employment. Can it express your variant structure, can it tell you what changed since a point in time, can it page deterministically, can it write in bulk, is it idempotent, does it push events, does it expose the completeness state, and can you get everything out. Ask them before the contract, in writing.

    One: can the API express what the interface shows?

    This sounds absurd and it is common. A platform whose interface presents a family, a product and its variants may expose an API that returns a flat list of sellable items with the parent relationship implied by a shared prefix.

    Test it with your own worst case, not with their sample data. Take the most awkward product you have, the one with three variant axes and an incomplete grid, and ask them to model it and show you the API response. If the response cannot round-trip that structure, everything you build on top will be flattening and re-inflating it, which is where data goes to get lost. The structure this has to survive is described in attributes, variants and the SKU problem.

    Two: how do you ask what changed?

    The single most consequential question, and the most often answered badly.

    You want a change feed: give it a timestamp or a cursor, get back everything modified since, including deletions. What you often get instead is a filter on a modified_at field, which is nearly the same thing and fails in two ways. It misses deletions entirely, because a deleted record has no row to carry a timestamp. And it misses records whose modification was caused by a related record changing, unless the platform propagates timestamps, which most do not.

    Ask specifically: does a change to a variant update the parent’s timestamp? Does a change to a shared attribute update every product using it? If the answer is no to either, your incremental sync will silently miss updates and you will discover it through a customer.

    Three: is pagination deterministic?

    Offset pagination over a changing collection loses and duplicates records. It is not a subtle failure; it is arithmetic. If a record is inserted before your current offset between page four and page five, one record is skipped, permanently, with no error.

    You want cursor or keyset pagination, where the cursor encodes a position in a stable ordering. Ask what happens when a record is inserted mid-traversal. A good answer describes the guarantee. A vague answer means offsets.

    Also ask about the page size ceiling and the rate limit together, because they multiply. A hundred records per page against sixty requests a minute means six thousand records a minute, which is fine at ten thousand products and not fine at two hundred thousand.

    A twenty-segment strip with the first three filled teal and joined by cursor arrows, an amber broken bracket spanning the rest

    Four: can you write in bulk, and what happens halfway through?

    Loading a catalogue one record at a time is slow enough to matter during migration and during any bulk correction.

    Two properties to establish. Whether there is a bulk endpoint that accepts many records in one call, and what its failure semantics are. A bulk call that fails atomically is easy to reason about. One that applies the first four hundred of five hundred records and returns a partial error is workable if it tells you precisely which ones. One that returns a generic failure after partial application is the worst case, and it is common.

    Ask for the shape of the error response before you believe the answer.

    Five: are writes idempotent?

    You will retry. Networks fail, jobs get rerun, someone double-clicks.

    An idempotent write means sending the same request twice leaves the same state as sending it once. The usual mechanism is an upsert keyed on your identifier, or an idempotency key you supply. Without one, a retry creates a duplicate, and duplicates in a product catalogue are unusually expensive because they propagate to channels before anyone notices.

    This is also the reason to key writes on your own stable identifier rather than on the platform’s internal one. Your identifier exists before the record does, which is what makes upsert possible.

    Six: does it push, or must you poll?

    Polling a catalogue for changes is a cost you pay forever, and its latency is bounded by how often you are willing to pay it.

    A platform that emits webhooks on create, update, delete and state change lets you react in seconds and stop scheduling anything. Ask about the delivery guarantees rather than just the feature: is delivery at least once, is there a retry policy, is the payload signed, and does the event carry enough to act on or only an identifier you must then fetch.

    At-least-once delivery is normal and fine, provided your handler is idempotent, which is the same property as question five viewed from the other side.

    A teal emitter firing three darts at receiver plates, two landing cleanly and one amber dart fallen short of a tipped-over receiver

    Seven: is the completeness state readable?

    The completeness model is the reason to buy a product platform at all, so it is worth checking that the number is available outside the interface.

    You want to query “which products are not ready for channel X, and which fields are missing”. If that exists only as a dashboard, you cannot build it into your own operational tooling, cannot alert on it, and cannot include it in a launch checklist that runs automatically. The operational value of that query is set out in running product content as an operation.

    Eight: can you get everything out?

    Ask it plainly. Can we export every record, every relationship, every version and every asset association, in a documented format, through the API, without a support ticket.

    The answer sets your exit cost, and it is the question that most reliably distinguishes vendors who expect you to stay because you want to from those who expect you to stay because you cannot leave. A confident answer is a good sign about everything else.

    What about the general shape of the API?

    Less important than the eight above, but worth noting.

    REST with sane resources is fine and is what most of this category ships. GraphQL is pleasant for read-heavy front ends because it avoids over-fetching, and Shopify’s admin API is a well-documented example of the style if you want to see one. Neither choice determines whether the integration will work; the change feed and the pagination do.

    Authentication should be OAuth 2.0 or scoped API keys with the ability to issue and revoke per integration. A single shared key with full access is a finding waiting to be written up.

    Custom fields deserve one specific question: are they first-class in the API, with the same query and filter capability as built-in fields, or are they a bag attached to the record? Shopify’s metafields are a reasonable reference point for what first-class looks like. If your extensions are second-class, everything specific to your business will be the slow path.

    How should you actually run this evaluation?

    Not as a questionnaire. Ask for a sandbox account and spend a day writing the smallest real integration: load fifty of your own products including the awkward one, change three of them, and pull the changes incrementally. That day answers six of the eight questions honestly, and it answers them about your data rather than theirs.

    The answers then feed directly into the integration design in wiring a DAM to a PIM and into the field ownership list in single source of truth applied to product data. The equivalent set of questions for the asset side is in DAM for developers.

  • Single source of truth, applied to product data

    Single source of truth, applied to product data

    Every architecture document contains the phrase. Every architecture built from those documents contains the same product title in four places, three of which are editable.

    The phrase is not wrong. It is just not a design until it names fields.

    Short answer: single source of truth means, for each field, exactly one system where it can be edited. Everything else holds a reference, or a clearly labelled read-only cache with a defined refresh. Written that way it is enforceable. Written as a principle it is a sentence everyone agrees with while building the opposite.

    Write it as a table of fields, not as a principle

    The artefact you need is unglamorous: a list of every field that appears in more than one system, with the system that owns it, and the systems that consume it. Fifty to two hundred rows for most catalogues.

    Producing it takes about two days and it is the highest-value two days in any integration project, because it converts an architectural opinion into a set of decisions people can disagree with specifically. Vague disagreement recurs forever. Specific disagreement gets resolved once.

    The rules that make the list decidable are in DAM vs PIM for two systems and the four-system boundary map when the CMS and ERP are involved. Single source of truth as a concept is old and stable; the work is entirely in the application.

    What a legitimate copy looks like

    Absolutism here is unhelpful, because some copying is necessary. A storefront that resolves every field from an upstream API on every page load is slow and fragile. The distinction is not copy versus no copy. It is governed copy versus ungoverned copy.

    A legitimate copy has four properties:

    It is read-only in the consuming system. Not by convention. Enforced, with the edit control absent from the interface. If a person can edit it, someone eventually will, and their edit will be silently overwritten or silently authoritative, and you will not know which.

    It has a defined refresh path. Either an event that invalidates it or an interval that bounds its staleness. “It gets updated when we run the job” is a schedule; “it is refreshed within a minute of a change event” is a contract.

    It is labelled as derived. In the schema, in the interface, and in the documentation. The next person to look at it should not have to work out whether it is authoritative.

    It exists because a specific query needs it. Not because it was convenient to have. The discipline of naming the query is what stops a read model growing into a full duplicate over a year.

    Anything with all four is a cache. Anything missing one is a second source of truth wearing a disguise.

    One pedestal holding a teal-edged plate with five dishes of translucent replicas around it, two of them solid amber and mismatched

    The three fields that always cause trouble

    Product title. Owned by the product record, and immediately wanted by the CMS for page titles, by the DAM for asset naming, and by search indexes. The trap is the CMS letting an editor “adjust it for this page”, which produces a per-page override that is invisible from the product side. If overrides are legitimate, model them as an override field with the original still visible. If they are not, remove the edit control.

    Price. Usually originates in the ERP or a pricing engine, is consumed everywhere, and is the field where staleness is most expensive. It should never be copied without a short and enforced refresh, and it is the strongest case in the catalogue for pushing changes rather than polling for them.

    Image association. Which images represent this product. Owned by the product record. Copied into the CMS as a page-level selection, which is legitimate if the CMS choice is understood as “which of the product’s images to place here” rather than as an independent list. When it becomes an independent list, images that were withdrawn upstream keep appearing on pages, which is the failure that reaches customers.

    Reference resolution beats field replication

    The pattern that keeps the list short is to store an identifier and resolve it, rather than storing the values.

    A product record holding an asset identifier is one field. The same product record holding the asset’s URL, dimensions, alt text, rights status and expiry date is five fields, all of which can go stale independently, and each of which is a row on your ownership list.

    The same applies in the other direction. A CMS page that stores a product identifier and resolves the title, price and images at render time has one field to govern. A page that stores copies of all three has three.

    The reason this is not obvious is that resolution has a cost, and the cost is paid at request time in a system somebody is measuring. It is worth paying, and where it is not, the answer is the governed cache above rather than an ungoverned copy. The mechanics are in wiring a DAM to a PIM, which works through the same decision for the asset side specifically.

    A schematic of one source feeding three caches with different refresh intervals, teal one-way arrows, and a struck-through amber reverse line

    How the list decays, and what to do about it

    The ownership list is accurate on the day it is signed and drifts from then on. Three things cause the drift.

    A new system arrives and nobody adds its fields. Usually a marketing tool, a review platform or an analytics product that turns out to be writing back.

    A migration inverts an ownership. A replatform moves a field’s home and the list still describes the old arrangement. This is the most dangerous kind, because integrations built after the migration will follow the code rather than the document.

    A shortcut becomes permanent. Someone enables editing in a consuming system to unblock a launch, and it is still enabled two years later.

    The countermeasure is small and boring. Review the list when any system in it is replaced, and once a year otherwise. Put the review on the same calendar as something that already happens. A list nobody reviews is a historical document, and the first time it misleads someone it will cost more than the review would have.

    What is the smallest useful version of this?

    Ten rows, on one page, covering the fields that appear in more than two systems. Title, price, description, images, category, stock, identifier, rights, approval state, and whichever tenth field your team already argues about.

    Write the owner. Write the consumers. Write, for each consumer, whether it references or caches, and if it caches, what invalidates it. Get the owner of each system to sign the page.

    That page is worth more than the diagram it will eventually be drawn as, and it is the input to what to demand from a PIM API before you buy, because an API that cannot resolve references cheaply will force you into caching decisions you did not want to make. The modelling groundwork underneath it is in the product data model that survives growth.

  • Do you need a PIM yet?

    Do you need a PIM yet?

    The answer most vendors will give you is yes, and the answer most consultants will give you is yes but later. Neither is wrong exactly. Both are unfalsifiable.

    Short answer: you need a PIM when at least two of four things are true. More than one market with genuinely different values, more than two channels with different required fields, more than one person editing the same records, and a variant structure a spreadsheet row cannot represent. One of the four is survivable. Two is the point where the spreadsheet starts costing more than the software.

    The four conditions, and why each one bites

    A second market with different values. Not a translated site. A market where units differ, where regulatory fields appear, where the category placement is not the same, and where copy has to be written rather than converted. A spreadsheet handles this by adding columns, and the column count becomes the problem: fields times markets, most of them empty, none of them validated.

    A third channel with its own required fields. Two channels can be handled with two tabs. At three, the tabs disagree, and the disagreement is discovered by a rejection report. The cost here is not the columns, it is that no single place tells you whether a product is ready.

    More than one editor. The moment two people edit the same file, you have a concurrency problem being solved by social convention. It works until a launch week, which is exactly when it will not.

    A variant structure that does not fit a row. One row per sellable unit means the product-level attributes are duplicated across every variant. One row per product means the variant data is crammed into a delimited string. Both are workable at small scale and neither survives a catalogue where variants outnumber products five to one. The modelling detail is in attributes, variants and the SKU problem.

    Notice what is not on the list. Revenue is not on it. Headcount is not on it. SKU count is only on it indirectly, because ten thousand simple products in one market on one channel are genuinely fine in a spreadsheet, and four hundred complex ones across five markets are not.

    What to do in the eighteen months before you need one

    This is the part that gets skipped, and it is the part that determines how bad the eventual migration is.

    Model properly now, in whatever you have. The four decisions in the product data model that survives growth can all be made in a spreadsheet. Typed columns, one column per attribute with a unit column beside it, a separate sheet for variants keyed to a parent, and an explicit note about what is localisable. A well-modelled spreadsheet migrates in an afternoon. A badly modelled one migrates over a quarter and mostly by hand.

    Use identifiers that will survive. A meaningless permanent internal SKU, never reused, plus a real GTIN where you sell through anyone else. This costs nothing today and is close to unfixable later.

    Keep the vocabularies as lists. A separate sheet per controlled field, and a validation rule pointing at it. You will not enforce everything a real system would, but the lists themselves are the asset, and they transfer.

    Write down the channel requirements. One page per channel, with its required fields and constraints, dated. This is the input to the rule sets you will eventually configure, and gathering it later, under time pressure, is miserable.

    Macro of a printed ruled grid on paper under raking teal light, one cell carrying an amber correction mark over the printed rule

    The media half of the question is different

    The threshold for a PIM is genuinely high. The threshold for putting media on a proper delivery layer is much lower, and the two questions get bundled together when they should not be.

    Product data in a spreadsheet has few second-order effects. Product images in a folder have several, and they start immediately: every channel needs a different shape, so someone produces crops; those crops become files; the files go stale independently; nothing records which one is current; and the front end serves whatever oversized JPEG it was given. That is happening at forty products, not at four thousand.

    This is where adopting something on day one genuinely pays, and it is a smaller commitment than the PIM decision. A delivery layer that derives renditions from a master by URL parameter removes the crop production step permanently, and it does so at a scale where nothing else about your operation needs to change. Cloudinary’s free Programmable Media tier covers 25 credits a month, where a credit is 1,000 transformations or 1 GB of storage or 1 GB of delivery, which is a real amount of capacity for a small catalogue rather than a trial.

    The argument for doing it early is not that you will grow. It is that the structure is there from the first upload, and the alternative is discovering at month eighteen that four hundred stored derivatives exist across three codebases with no record of which master they came from. The developer-facing version of this is in DAM for developers.

    What if you buy one too early?

    You get three things you did not need and one you did.

    The three: a workflow to maintain, a schema you configured before you understood your own catalogue, and a licence line. The one: enforcement, which genuinely does improve data quality even for a small catalogue.

    Buying early is not a disaster. It is a cost with a modest benefit, and the real risk is that you configure the schema wrong while you are still learning what your product data looks like, then live with that configuration for years because reconfiguring is a project. This is the strongest argument for modelling on paper first, which costs an afternoon and is reversible.

    A horizontal bar in three zones, three pale squares in the first, nine in the second, thirty tightly packed in the third with four in amber

    What if you wait too long?

    You get a migration with a data cleanup attached, and the cleanup is the expensive half. It is also the half that cannot be parallelised, because it consists of decisions about values only a few people can make.

    The signals that you are past the point are specific. Someone maintains a document explaining which spreadsheet is the real one. A launch slips because two versions of a file diverged. A channel rejection takes more than a day to attribute to a field. Any of those means the cost has already moved from the software to the operation, which is a worse place for it to sit.

    So what should you do this quarter?

    Three things, in this order, none of which requires a purchase.

    1. Test yourself against the four conditions honestly. If fewer than two are true, do not buy a PIM. Revisit in six months.
    2. Fix the model where you are. Types, variants, localisable fields, identifiers. This is the work that makes the eventual purchase cheap.
    3. Put the media on a delivery layer now, because that threshold is lower and the debt accrues faster.

    When two conditions do become true, what a DAM and a PIM actually cost sets out what to budget, build versus buy for the product catalogue covers the case for assembling it yourself, and alternatives to buying a DAM and a PIM covers what you can do with tools you already pay for. The system boundary you are buying into either way is in DAM vs PIM, and the honest description of what the category does is in what a PIM actually does.

  • Running product content as an operation

    Running product content as an operation

    The autumn range launches. Six weeks of long days, a shared spreadsheet, three people working evenings, and a launch that mostly holds together. Then everyone goes back to their real jobs, and in January the spring range starts and none of it is written down.

    The work was not the problem. The absence of an operation was.

    Short answer: product content is a repeating process with a measurable throughput, not a series of projects. Give it named roles, a definition of done per stage, a queue with a service level, and a capacity plan that accounts for peak. The gains come from removing waiting, not from working harder during the six weeks.

    Four roles, whoever holds them

    These are functions, not headcount. In a small team one person holds three of them, and that is fine as long as everyone knows which hat is on.

    Producer. Owns the schedule and the sample flow. Knows what is arriving, what is booked, and what is late. This is the role most often unfilled, and its absence shows up as samples that arrive without a shoot slot.

    Cataloguer. Owns the record. Attributes, taxonomy placement, completeness against each channel. Cares about the model and is the person who notices when a new product does not fit it.

    Asset owner. Owns the library. Ingest, metadata, rights, versions, and the answer to “which one is current”.

    Approver. Owns the decision, and only the decision. If the approver is also doing the work, approval is not a control, it is a formality.

    The common failure is that the cataloguer and asset owner are the same overloaded person, and the queue between their two jobs is invisible because it is inside one person’s head.

    A definition of done for each stage

    Half of all rework in this pipeline is caused by work moving forward before it was finished, because “finished” was never written down.

    Write one sentence per stage. For example: shoot is done when every frame on the shot list exists, is in focus, and is named or tagged with the SKU. Ingest is done when the assets are in the library, associated with a product, and carry creator, date and rights. Enrichment is done when the record passes the completeness rule set for every channel it is destined for. Approval is done when a named person has recorded a decision with a date.

    These sentences are boring and they eliminate the most expensive class of problem, which is work that has to travel backwards. A queue that flows one way at a steady rate is fast even when each stage is slow. A queue that flows backwards is slow no matter how fast each stage is.

    A cumulative flow chart, teal completed band rising steadily, pale in-progress band steady, amber waiting band widening sharply on the right

    Measure throughput and waiting, and nothing else at first

    Two numbers, tracked weekly, will tell you more than a dashboard.

    Throughput. Products fully published per week. Not products touched, not assets processed. Completed.

    Waiting. For products currently in flight, how long since each last moved. Sorted descending, this is your problem list, and the top ten items are usually the same three causes.

    Resist adding more metrics until those two are stable. Utilisation in particular is a trap: a pipeline where everyone is a hundred per cent busy has no slack, and a queue with no slack has a waiting time that grows without bound. The team that looks slightly underloaded is often the one shipping faster.

    The mechanics of finding where the waiting is concentrated are in the product image workflow, which walks through instrumenting the handoffs.

    Capacity planning for a peak that happens every year

    Seasonal peaks are not surprises, and the plan for them should not be overtime.

    Work out the peak in units per week rather than in feelings. Six hundred products over eight weeks is seventy-five a week, against a steady-state throughput you now know. If steady state is forty, you need either double the capacity for eight weeks or a longer runway, and both of those are decisions to make in advance rather than discoveries to make in week three.

    Three levers, in order of preference:

    • Start earlier. The cheapest capacity is a longer window, and it usually requires only that samples arrive sooner.
    • Reduce the work per unit. Removing the crop production step, standardising the shoot setup, and generating variant records instead of typing them all reduce the per-unit cost permanently rather than for one season.
    • Add hands. Real capacity, real cost, and the least effective of the three if the bottleneck is approval rather than production, because adding producers to an approval-bound pipeline just lengthens the queue.
    Four cards in a row joined by teal arrows, the second arrow doubled in amber and looping backwards from the third card to the second

    Standards, kept short enough to be read

    Every operation accumulates a document nobody opens. Keep three, each on one page.

    The shoot standard. Setup, lighting, angles per category, and the shot list template. This is what makes this season’s images match last season’s, which matters more on a product grid than any individual image quality.

    The metadata standard. Which fields are mandatory at which stage, what the controlled vocabularies are, and who maintains them. Not the full schema, just the operating rules on top of it.

    The naming and identifier standard. What the SKU means, what the asset identifier means, and the explicit rule that neither is ever reused. Reuse is the single most damaging convention violation in this domain, because it silently corrupts history.

    If a standard is longer than a page it is a reference document, which is fine, but it is not the thing people follow during a launch week.

    What is the smallest version of this that works?

    For a team of three, running a few hundred products a season, the whole operation fits in one page and one board.

    Write the four roles on it with a name against each, even if two names repeat. Write the definition of done for each stage. Put every product on a board with one column per stage and a hard limit on how many can sit in any column at once. Review the waiting list once a week for fifteen minutes and fix the top cause.

    That is enough to stop each season being a rebuild. Software helps once the process exists and reliably formalises the wrong thing when it does not, which is the same warning as in the product image workflow. When a launch does come, the catalogue launch checklist is the pre-flight version of this page, the channel-facing half of the work is in syndicating product data to marketplaces, and the capacity question specific to imagery is in product photography without a studio backlog.

    Two external references worth keeping near the metadata standard: the IPTC photo metadata specification for what travels inside an image file, and the Dublin Core terms as a sanity check on your own descriptive fields. Neither is a system to adopt wholesale. Both are useful for settling arguments about what a field is supposed to mean.

    Related field note

    Continue with A practical checklist for product photography handoffs.

  • Syndicating product data to marketplaces

    Syndicating product data to marketplaces

    The feed goes out on Monday. On Thursday a report says four hundred listings were rejected. The reasons are terse, the affected SKUs are listed by the marketplace’s own identifier rather than yours, and nobody can tell whether it is the same four hundred as last week.

    That loop is the entire problem, and it is a loop you can close.

    Short answer: treat every channel’s requirements as a declared rule set, hold the union of all of them in one record, and validate against each rule set before publishing rather than after. Rejection then happens in your system, attributable to a field and a person, instead of arriving three days later in someone else’s format.

    What a channel actually demands

    Pull apart any marketplace specification and it contains four kinds of requirement, which is useful because each needs a different mechanism.

    Required fields. Present and non-empty. Easy to check, and the most common cause of rejection.

    Format constraints. Title under a length, description without HTML, price with two decimals, image at a minimum resolution and aspect ratio. Also easy to check, and routinely missed because the constraint is buried in a PDF.

    Vocabulary mapping. The channel’s category tree, its colour list, its size conventions. Your Navy has to become their Blue, and there is no way to derive that. It has to be maintained as a mapping.

    Identity. A valid GTIN with a computing check digit, or an approved exemption. This is increasingly non-negotiable and it is the failure that takes longest to fix, because obtaining identifiers is an external process.

    Google’s product data specification is the best public example to read if you want to see all four in one document, and its shape is broadly representative of what the larger marketplaces want.

    Hold the union, generate the shapes

    The instinct is to build a record per channel. It works for two channels and collapses at four.

    The alternative is one record holding the union of every field any channel needs, plus a mapping layer per channel that selects, renames, converts and constrains. The record does not know about channels. The mapping does not hold data. Adding a fifth channel is then a new mapping and possibly a few new fields, rather than a fifth copy of everything.

    Two properties make this work in practice:

    Mappings are declarative. A mapping should be a document that says which source field becomes which target field, with which transformation. When mappings are code, only the person who wrote them can answer a question about them, and channel specifications change often enough that this matters.

    Generation is idempotent. Running the same export twice produces the same output, and publishing it twice produces the same state at the channel. Without that property you cannot safely retry, and you will need to retry.

    A schematic of one source block feeding six transform blocks each emitting one output, two of the blocks amber with a rejection arrow curving back

    Validate before you publish

    This is the change that removes most of the pain, and it is the reason the completeness model in what a PIM actually does exists.

    Score every product against every rule set it is meant to satisfy, continuously. Show the result as a per-channel completeness figure with the missing fields named. Block publication for a product that does not pass. The queue of work then lives in your system, sorted by channel and field, and it can be assigned.

    Compare that with the alternative, which is that the channel validates for you, in its own time, and reports in its own vocabulary. The information is the same. The latency and the attribution are not, and those are what determine whether anything gets fixed.

    One caution worth stating: a completeness score is only as honest as the rule set behind it. Rule sets drift when a channel updates its specification quietly, which they do. Put a date on each rule set and review it, or your green dashboard will eventually be measuring last year’s requirements.

    Images are part of the feed and they fail differently

    Channels have image requirements: minimum dimensions, aspect ratio, background colour, no text overlay, a maximum file size, sometimes a specific format. These are the requirements most likely to be met by generating rather than by finding.

    If your renditions are derived from a master by parameter, meeting a new channel’s image spec is a mapping entry rather than a production task. A square crop on white at 2000 pixels for one marketplace and a 4:5 crop for another are two parameter strings against the same master, not two files someone makes and stores. The rendition model is what makes that possible, and it is the difference between adding a channel in an afternoon and adding one in a sprint.

    The image identity question is separate and worth being careful about. Some channels key on image URL and will re-fetch when it changes; others cache the first version they saw. Use stable URLs for the same content, change the URL when the content genuinely changes, and never reuse a URL for a different image.

    A tray of small embossed metal labels under raking teal light, five in the third row stamped off-centre and lit amber

    Rejection handling as a first-class flow

    You will still get rejections, because channels enforce things they did not document. Treat that as a routine flow rather than an incident.

    • Map their identifier back to yours on ingest, so a rejection report arrives as your SKUs. This single step saves more time than any other.
    • Classify by cause, not by product. Four hundred rejections are usually six causes. Fix the cause and the four hundred resolve together.
    • Feed the cause back into the rule set. Every undocumented rule you discover becomes a check you run before publishing, permanently. This is how the rule sets become more accurate than the specifications.
    • Keep the history. The same product failing repeatedly for different reasons means the record is thin, not that the channel is difficult.

    How often should a feed run?

    Less often than you think for the full catalogue, and much more often than you think for changes.

    A full regeneration is a reconciliation, not an update. Run it on a schedule that suits the channel’s tolerance, typically daily or weekly, and treat divergence found by it as a bug in the change path rather than as normal operation.

    Changes should propagate on change. Price and stock in particular have a short useful life, and a channel showing yesterday’s stock costs you more than the engineering to push it. Where a channel only accepts scheduled files, generate the file from live data at generation time rather than from a staged copy you maintain, which is the same argument made about internal integrations in wiring a DAM to a PIM.

    The structural prerequisite for all of this is a model that can express what the channels ask for. If yours cannot represent a variant grid or a localised attribute, the mapping layer will end up carrying data, which is where syndication projects go to die. Attributes, variants and the SKU problem and the product data model that survives growth cover that groundwork, and the human side of keeping the queue moving is in running product content as an operation.

  • Media in a headless commerce stack

    Media in a headless commerce stack

    The headless migration goes well. The catalogue is an API, the storefront is a separate application, a second front end appears for the app, and a third for the in-store screens. Then someone notices the app is downloading two megabyte hero images to a five inch screen, and the fix is a ticket in three repositories.

    Short answer: in a headless stack the product API should return an asset identifier and a canonical delivery URL, never a set of pre-baked sizes. Each front end appends the parameters it needs at request time. That keeps the shape decision in the front end that knows the viewport, and the asset decision in the system that owns the asset, which is the only split that stays stable as you add channels.

    What headless changes about media

    Headless architecture removes the assumption that there is one front end. That assumption was carrying more weight than anyone realised, because it was also the assumption that let you decide image sizes once, centrally, at build time.

    With one front end, a fixed set of renditions is workable. You know the breakpoints, you generate five sizes, you are done. With four front ends on different frameworks, different devices and different release cycles, a fixed set is wrong for at least three of them within a quarter, and the process for adding a size is a cross-team negotiation.

    The second thing headless changes is who is holding the responsibility. In a monolith the platform knew both the layout and the asset. Split them and neither side knows both, so the contract between them has to carry enough information for the front end to decide.

    The API contract that works

    Return three things per asset, per product:

    A stable identifier. Opaque, permanent, meaningful only to the asset system. This is what the product record stores, for the reasons in wiring a DAM to a PIM.

    A canonical delivery URL. The base from which any rendition can be constructed by appending parameters. Not a rendition itself.

    Enough metadata to render responsibly. Intrinsic width and height, so the front end can reserve space and avoid layout shift. The default description, so alt text exists without another call. Focal point if you have one.

    That is the whole contract. Notably absent: a list of sizes. The moment the API returns thumbnail, medium and large, you have encoded three front ends’ assumptions into a shared interface, and the fourth front end will either misuse one of them or ask for a fourth name.

    Let the front end ask for what it needs

    With a URL-parameter delivery layer, each surface constructs what it wants at request time. A Cloudinary URL is the clearest example of this contract in practice, because the parameters sit in the path and can be generated by the consumer without a round trip.

    For a responsive web front end the useful set is narrow. Ask for automatic format so AVIF and WebP go to browsers that support them and JPEG to those that do not, which is what the format support matrix otherwise makes you handle by hand. Ask for automatic quality so compression is chosen per image. Then emit a srcset with the widths your layout actually uses, following the responsive images guidance, and let the browser choose.

    For a native app, ask for the device pixel ratio you have and nothing else. For a screen in a store, ask for the fixed size of the screen. Each surface answers a question only it can answer, and none of them need a deployment in another repository to do it.

    The performance argument for this is not subtle. Images are usually the largest contentful paint element on a product page, and serving a correctly sized modern format is most of the fix. Delivering WebP or better instead of an oversized JPEG typically moves that metric more than any front-end optimisation you will do this quarter.

    One source square linked by teal parameter lines to eight differently proportioned outputs, with the same eight redrawn in amber inside a hatched storage container

    Caching, which is the part that surprises people

    A derived-rendition model produces a very large number of distinct URLs, and that is fine, because each one is immutable.

    The rules that keep it fast:

    • Make the URL the cache key and make it deterministic. The same parameters must produce the same URL every time, in every front end. A shared helper is worth more than a documented convention.
    • Cache derived output aggressively and for a long time. An immutable URL can be cached effectively forever, following the standard HTTP caching guidance. The first request pays the transformation cost and nothing else does.
    • Version by identifier, not by cache busting. When an asset is replaced, the identifier or version component changes and the old URL simply stops being referenced. Purging a CDN by pattern is a thing you should never need to do routinely.

    The consumption implication matters for the bill as well. Repeated delivery of an already-generated derivative does not re-run the transformation, so the cost of the long tail of URLs is storage and bandwidth rather than compute.

    Do not put media logic in the front end

    The failure mode of a headless stack is that each front end grows its own image utility, and after a year the four utilities disagree.

    Keep a single shared definition of the shapes your business uses. Named transformations are the mechanism if you are on a platform that supports them: define product_card, product_hero, swatch once, and let every front end reference the name. When the design changes, the definition changes and every surface follows, without a coordinated release.

    If your delivery layer has no such feature, achieve the same thing with a small shared package that constructs URLs. The important property is that the parameters exist in exactly one place.

    Nine flat edge nodes ringing a teal-edged origin cube, three of them holding an amber cube that does not match the origin silhouette

    When is a headless media layer overkill?

    If you have one front end and no plans for a second, most of this page is theory. A monolithic storefront with a built-in media library, a sensible set of breakpoints and a CDN in front of it is a perfectly good architecture and will outperform a badly assembled headless stack.

    The threshold is the second surface. The moment a native app, a marketplace, a partner site or a physical screen consumes the same catalogue, the assumptions that made a fixed rendition set workable stop holding, and every month you delay makes the change larger.

    That is also the reason to put the delivery layer in early rather than after the second front end arrives. Adopting it on day one costs a URL helper and an account. Adopting it in month eighteen means finding every hard-coded image path in three codebases and every stored derivative in the catalogue. The developer-side version of that argument is in DAM for developers, and the properties an asset needs in order to be addressable this way are in what a DAM actually does. If you are also choosing a product API, what to demand from a PIM API before you buy covers the other half of the contract.

    Related field note

    Continue with How to measure headless commerce media.

    Related field note

    Continue with A practical checklist for headless commerce media.

  • What a DAM and a PIM actually cost

    What a DAM and a PIM actually cost

    Every quote you receive will be for the licence. Every project that goes wrong goes wrong on one of the other four lines.

    Short answer: budget the licence at roughly a third of year one and less than half of year two. The lines that get missed are data cleanup before go-live, integration work on both sides, and the ongoing human effort of keeping records complete, which no platform removes and several make more visible. If a business case does not name those three, it is not a business case.

    The five lines

    Licence or subscription. Priced per user, per SKU, per asset, per gigabyte, or per some blend. This is the negotiable one and it is the one everyone negotiates, usually at the expense of attention to the others.

    Implementation. Configuration, schema build, channel mappings, and the integration work on both ends. Frequently sold as a fixed-price package that covers the first two and not the third. Ask explicitly who is building the connection to your storefront, because “we have an integration” often means “there is an API”.

    Data preparation. Cleaning, deduplicating and completing what you already have, before it can be loaded. This is the line most often estimated at zero and it is almost never zero. If your current data were clean you would probably not be buying anything.

    Ongoing content work. Someone still has to write the copy, enter the attributes, tag the assets and approve them. A good system makes this work visible and routes it. It does not do it. This is the largest line over three years and it exists whether or not you buy anything, which is why it is often left out and why leaving it out distorts the comparison.

    Rework. Everything you have to redo because a decision made in month two turned out wrong in month eight. You cannot budget it precisely; you can reduce it by modelling before choosing, which is the argument in the product data model that survives growth.

    What the pricing models actually do to you

    The unit of pricing shapes behaviour more than the price does, and this is worth thinking about before the negotiation.

    • Per user encourages shared logins, which destroys your audit trail and is usually a contract breach.
    • Per SKU makes you reluctant to load the long tail, which is exactly the part of the catalogue that most needs structure.
    • Per asset makes people delete masters to save money, which is the opposite of what an asset library is for.
    • Per gigabyte of storage is mostly benign, since storage is cheap and predictable.
    • Per gigabyte of delivery is fine while you are small and becomes the number to watch if a campaign goes well.
    • Consumption credits pool several of these, which makes the bill harder to forecast and easier to control, because you can trade one kind of usage against another.

    Cloudinary is a public example of the last model, and it is worth reading as a shape rather than as a recommendation at this point in the page. Its Programmable Media plans start at a free tier of 25 credits a month, then $99 a month for 225 credits, and $249 a month for 600. A credit is 1,000 transformations, or 1 GB of managed storage, or 1 GB of delivered bandwidth, spent across those as you use them. Cloudinary Assets, the DAM side, has a free tier at 25 GB of storage with enterprise pricing above it.

    The practical consequence of a pooled model is that a small team can carry a real asset library and real delivery on nothing, which is unusual in this category and which changes the build-versus-buy arithmetic in build versus buy for the product catalogue.

    A long statement on paper with a column of empty line items, teal section rules, four items struck through in amber

    The shape over three years

    Year one is licence plus implementation plus data preparation, and it is the big number. Year two is licence plus the ongoing content work plus whatever integrations you deferred. Year three is where the total cost of ownership comparison actually gets decided, because by then the implementation cost has amortised and what remains is the running cost of the operating model.

    Two patterns are worth expecting.

    The cheap licence with expensive integration. Common in the DAM category. The platform is affordable and every connection to it is a project. Total is higher than the quote by a factor that depends entirely on how many systems you have.

    The expensive licence with everything included. Common at the enterprise end of PIM. The number is large, visible and survivable, and the risk moves from cost to lock-in, because the included integration work is built in a way only that vendor can maintain.

    Neither is a trap exactly. They are different distributions of the same total, and which suits you depends on whether you have engineering capacity or budget, which is rarely both.

    The line nobody quotes: getting out

    Ask two questions in the first meeting, before the demo.

    Can you export everything, including relationships and history, in a documented format, on demand, without a support ticket? The answer determines what you will pay to leave. “We can arrange an export” is not the same answer as “here is the API endpoint”.

    Do your assets keep working during a migration? If URLs are tied to the vendor’s domain and the identifiers are internal, then leaving means changing every URL in every channel, which is a cost you incur once and remember forever.

    Neither question offends a good vendor. The reaction is itself information.

    A teal line falling and flattening against a pale line climbing past it, crossing at eighteen months, marked with a thin amber rule

    What should a small team actually budget?

    Rough shapes, for a team under fifteen people with a few thousand SKUs. These are planning figures rather than quotes, and the point is the ratio rather than the absolute.

    • Do nothing yet. Spreadsheet plus the storefront’s own fields and media library. Cost is the content work, which you are already paying. This is the right answer more often than the category admits, and do you need a PIM yet is the test.
    • Media layer only. A delivery and asset platform on a free or low tier, no PIM. Costs tens per month at small scale, removes the crop and format work permanently, and is reversible.
    • PIM only. Entry tiers in this category start in the low hundreds per month. Add the same again for implementation in year one, and count on someone spending real time on channel mappings.
    • Both, properly implemented. Assume a five-figure year one including implementation, and half of that ongoing. If the quote is materially below that, check which of the five lines has been left out.

    The alternatives to spending any of it, including what you can assemble from tools you already pay for, are in alternatives to buying a DAM and a PIM. The boundary question that determines whether you need one system or two is in DAM vs PIM.