惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

N
News and Events Feed by Topic
S
Security @ Cisco Blogs
S
Secure Thoughts
Attack and Defense Labs
Attack and Defense Labs
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
Hacker News - Newest:
Hacker News - Newest: "LLM"
Recent Commits to openclaw:main
Recent Commits to openclaw:main
H
Hacker News: Front Page
博客园 - 叶小钗
H
Heimdal Security Blog
Microsoft Security Blog
Microsoft Security Blog
Forbes - Security
Forbes - Security
AI
AI
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
T
Troy Hunt's Blog
罗磊的独立博客
Application and Cybersecurity Blog
Application and Cybersecurity Blog
爱范儿
爱范儿
GbyAI
GbyAI
The Last Watchdog
The Last Watchdog
TaoSecurity Blog
TaoSecurity Blog
C
CXSECURITY Database RSS Feed - CXSecurity.com
D
DataBreaches.Net
Recent Announcements
Recent Announcements
Schneier on Security
Schneier on Security
C
Cisco Blogs
美团技术团队
D
Docker
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
WordPress大学
WordPress大学
月光博客
月光博客
雷峰网
雷峰网
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
H
Hackread – Cybersecurity News, Data Breaches, AI and More
A
Arctic Wolf
B
Blog RSS Feed
Cisco Talos Blog
Cisco Talos Blog
C
Cybersecurity and Infrastructure Security Agency CISA
V
Vulnerabilities – Threatpost
V2EX - 技术
V2EX - 技术
Y
Y Combinator Blog
N
News and Events Feed by Topic
www.infosecurity-magazine.com
www.infosecurity-magazine.com
W
WeLiveSecurity
Security Archives - TechRepublic
Security Archives - TechRepublic
G
GRAHAM CLULEY
Jina AI
Jina AI
Hugging Face - Blog
Hugging Face - Blog
酷 壳 – CoolShell
酷 壳 – CoolShell
The Hacker News
The Hacker News

DEV Community

Authentication Security Deep Dive: From Brute Force to Salted Hashing (With Java Examples) Why AI Systems Don’t Fail — They Drift Spilling beans for how i learn for exam😁"Reinforcement Learning Cheat Sheet" I Replaced Chrome with Safari for AI Browser Automation. Here's What Broke (and What Finally Worked) How Python Borrows Other People's Work The $40 Architecture: Processing 1 Billion API Requests with 99.99% Uptime Vibe Coding: A Workflow Guide (From Zero to SaaS) Most webhook security guides protect the wrong side. The scary part is delivery. Headless CMS for TanStack Start: Build a Blog with Cosmic EU Age Verification App "Hacked in 2 Minutes" — What Actually Happened Comfy Cloud’s delete function does not actually remove files Running AI Models on GPU Cloud Servers: A Beginner Guide Event-driven media intelligence with AWS Step Functions and Bedrock I scored 500 AI prompts across 8 quality dimensions — here's what broke How to Call Google Gemini API from Next.js (Free Tier, No Backend Needed) The Portal Protocol: Reclaiming Human Connection in the Age of AI How to Fix Your Team's Scattered Knowledge Problem With a Self-Hosted Forum Intro to tc Cloud Functors: A Graph-First Mental Model for the Modern Cloud Designing Multi-Tenant Backends With Both Ownership and Team Access I Built a Neumorphic CSS Library with 77+ Components — Here's What I Learned PostgreSQL Performance Optimization: Why Connection Pooling Is Critical at Scale Cómo construí un SaaS multi-rubro para gestionar expensas en Argentina con FastAPI + Vue 3 🚀 I Built an Ethical Hacking Scanner Tool – Open Source Project I Replaced /usage and /context in Claude Code With a Single Statusline A Pythonic Way to Handle Emails (IMAP/SMTP) with Auto-Discovery and AI-Ready Design I Collected 8.9 Million Polymarket Price Points — Here's What I Found About How Markets Really Move EcoTrack AI — Carbon Footprint Tracker & Dashboard Everyone's Using AI. No One Agrees How. 5 self-hosted ebook managers worth trying in 2026 Building Your First AI Agent with LangChain: From Chatbot to Autonomous Assistant Common SOC 2 Failures (Real World) Stop Vibe-Checking Your AI App: A Practical Guide to Evals How to Use SonarQube and SonarScanner Locally to Level Up Your Code Quality Your Next To-Do App Is Dead — I Replaced Mine with an OpenClaw AI Sign a Nostr event in 60 lines of Python using coincurve — no nostr-sdk, no nbxplorer, no rust toolchain ITGC Audit Explained Like You’re in Big 4 Patch Tuesday abril 2026: Microsoft parcha 163 vulnerabilidades y un zero-day en SharePoint Stop scraping everything: a better way to track competitor price changes Listing on MCPize + the Official MCP Registry while routing payments OUTSIDE the marketplace — how I kept 100% of my x402 revenue Building an AI-Powered Risk Intelligence System Using Serverless Architecture Why We Ripped Function Overloading Out of Our AI Toolchain Testing AI-Generated Code: How to Actually Know If It Works SaaS Churn Is Killing Your Business. Here Is What to Do About It (Without a Support Team) The Speed of AI Is No Longer Linear - And Self-Improving Models Are Why How to Implement RBAC for MCP Tools: A Practical Guide for Engineering Teams From Standard Quote to Persuasive Proposal: AI Automation for Arborists I built a CLI that scaffolds complete multi-tenant SaaS apps Axios CVE-2025–62718: The Silent SSRF Bug That Could Be Hiding in Your Node.js App Right Now The dashboard that ended our friendship Data Pipelines Explained Simply (and How to Build Them with Python) The Hidden Cost of AI Systems Nobody Talks About. undefined vs undeclared, and how typeof behaves Switching from file-based jobs to NATS/Kafka in Rust without changing code io_uring Adventures: Rust Servers That Love Syscalls Why Agentic AI is Killing the Traditional Database The POUR principles of web accessibility for developers and designers Quantum Neural Network 3D — A Deep Dive into Interactive WebGL Visualization How To Install Caveman In Codex On macOS And Windows Automation Pipeline Reliability: Why Your Workflow Breaks When Nobody Is Watching I Built an 'Open World' AI Coding Agent — It Works From ANY Folder From Freelancing to Product: A Tech Service Company's SaaS Transformation China's AI Giants: Adding Tencent Hunyuan & ByteDance Doubao to AI University (74 Providers) On the Vibe Coders and Their Lies clerk: Auto-Summarize Your Claude Code Sessions AI Weekly — 2026/04/10–04/17 | The Model Lockdown Is Here, but the Toolchain Is the Real Battleground AI 週報 — 2026/04/10–2026/04/17 模型封鎖潮來了,但工具鏈才是真戰場 Maybe this is how Open-Source apps are born... 🚀 Fine-Tune LLMs with LoRA and QLoRA: 2026 Guide tRPC v11 + Next.js App Router: End-to-End Type Safety Without the Boilerplate ShadCN UI in 2026: Why I Stopped Installing Component Libraries and Started Owning My Components SaaS Billing in React Server Components: Stripe + Supabase Without a Single `useEffect` Join our DEV Weekend Challenge — $1,000 in Prizes Across TEN winners! Submissions Due April 20 at 6:59 AM UTC. Implementing FSRS Spaced Repetition in Flutter + Supabase — Adding Memory Science to an AI Learning App "I Texted My Localhost From the Train — Claude Code Fixed the Bug Before I Got Home" I Built a Sales Prep AI and It Went Deeper Than Expected Design to Code #2: One JSON, Eleven Outputs Solving the 100M-Row Problem: A Summary Table Pattern for High-Volume Push Notification Logs Flutter Web With Wasm: What Actually Changes For Developers I Built 50 Royalty-Free Soundtracks for My Side Project in a Weekend Using AI Music Generation The Vibe Coding Security Checklist: 7 Things to Check Before You Ship Stop Letting Googlebot Guess Fix Your React App's SEO Right Desconstruindo o Streaming do LinkedIn: Como Criar um Engine de Extração de Vídeo de Alta Performance com HLS e FFmpeg (EDA Part-1) EDA (Exploratory Data Analysis) Explained With Real Life — Why Looking at Your Data Is the Most Important Step in Machine Learning Brand Relationship Management at Scale: Our 4-Touch Outreach System for 200+ Brands Why String.fromEnvironment() Might Return an Empty String in Dart JGuardrails 1.0.0 — Hardening Java LLM Apps Against Jailbreaks, Toxicity, and Prompt Injection Plan and Schedule a Full Week of Threads Content From One Claude Conversation Coding Cat Oran Ep3, Five Tables Changed Everything Updated: BFF Pattern I'm done watching freelancers get buried by 200 proposals. So I'm building the alternative. This is my first post BFS Algorithm in Java Step by Step Tutorial with Examples Tracking LLM Pricing Monthly: An Open Dataset for 22 AI Models How We Measure Content ROI on a Comparison Site: Revenue Attribution Without Perfect Data Introducing Nova AI Ops: The AI-Native Operating System for SRE Teams I built a free desktop video downloader for Windows — Grabbit How Talkie OCR Helps Vision-Impaired & Dyslexic Users Read the World Around Them VRCFaceTracking安装和iPhone面捕配置教程,有bug Even CrowdStrike Can't See Your Agents The Automation Gold Rush: What n8n Workflows and Claude Are Opening Up for Developers Right Now
Four-dimension valuation: my method
Michel Faure · 2026-05-01 · via DEV Community

Comic strip — Michel crosses out single-metric ARR at the whiteboard, builds a four-dimension framework (SaaS, Usage, Data, Strategic), and a CFO replies

Hook

After burying the "lines × day-rate with AI discount" method for my 91,000-line ERP, I found myself facing a harder question than the first one. What do I replace it with? I spent two days testing every single-dimension model available. None held. Here is the graveyard of my attempts, and what eventually worked: four dimensions, summed, not weighted, with a SQL deduplication rule that took me a week to find.


If you have 30 seconds. No single metric holds for valuing an internal ERP: ARR, SaaS replacement cost alone, usage value alone — all of them flatten reality. This article proposes a method of four summed dimensions (SaaS equivalent, usage, data, strategic), with the TypeScript consolidation function, the SQL deduplication query between dimensions, and the weekly cron that produces a defensible snapshot. Useful if you have to justify the value of software without a market price.

The graveyard of single-dimension models

First attempt, ARR. The preferred method of SaaS pitches, clean, universally understood. I opened a sheet, typed three formulas, and understood within fifteen minutes that I had no recurring revenue to put in it. Rembrandt is an internal tool, not a product I sell. ARR dead in fifteen minutes.

Second attempt, SaaS replacement cost. The idea: "what L'Atelier Palissy would pay in subscriptions if Rembrandt didn't exist." I listed Odoo, Brevo, Monday, Digiforma, Edusign. Monthly total around 425 euros, or roughly a hundred thousand over five years, discounted. Defensible in front of an accountant. But wrong the other way: no market SaaS covers the 10,000 lines of logic for four catch-up periods per year across six sites with Qualiopi rules. The counterfactual under-values what is precisely what makes the tool specific. Model dead one Sunday night.

Third attempt, usage value alone. "How many hours Rembrandt saves Françoise, Hélène, Catherine, Claire." The measure most aligned with real economics, by far. But inapplicable without friction: timing someone at the office is socially costly, and quarterly self-reporting is biased by the mood of the day. I started drafting a Google form. I closed it. Model dead before birth.

The diagnosis fits in one sentence. Rembrandt is a composite asset that mixes code, data, avoided labor, and strategic optionality. Applying a single metric to it flattens at least three of those dimensions. They all four have to be recognized.

The four dimensions

Dimension What it measures Method Fragility point
1. SaaS replacement cost The market counterfactual Σ equivalent subscriptions × 12 × NPV 5 years at 8% Undervalues the non-substitutable
2. Usage value Human productivity freed Hours/quarter × loaded hourly cost × NPV 5 years Not instrumentable without friction
3. Data patrimony The non-regeneratable intangible asset Volumes × market unit price + ADR capital Market unit price unstable
4. Strategic value Optionality and sovereignty Scores 1–10 on 4 axes (velocity, lock-in, AI…) Opinion-driven, assumed

Each measures something real that the other three don't see. Dimension 1 sees the market but not the singular. Dimension 2 sees human time but not data. Dimension 3 sees patrimony but not usage. Dimension 4 sees possible futures but nothing of what exists today. None is reducible to another. That's precisely what forces having four.

The aggregation rule: sum rather than max

This is the central methodological point, and it's the one that gets debated the most.

Why not the maximum. Taking the max ("the dimension that values the most wins") is a rhetorical move, not a method. It hides three of the four dimensions and produces a number that doesn't say what it measures. You fall back into single-dimension through the back door.

Why not the average. The average dissolves the difference in nature between dimensions. To say that Rembrandt's valuation is on average SaaS, human time, data and strategic is to claim they are commensurable when they precisely are not.

Why no weighted coefficients. Weighting introduces an additional arbitrariness that is no more defensible than the initial choice of dimensions. You solve one problem by creating another, less visible one.

That leaves the sum. It is not a natural aggregate, it is an explicit choice. It asserts that each dimension exists independently, that the system is worth their cumulation, and that every displayed euro is traceable to a source and a method.

In code, the heart of the calculation fits in twelve lines:

// lib/valorisation/compute.ts
type Dim = { id: DimId; low: number | null; high: number | null }

export function consolidate(dims: Dim[]) {
  const present = dims.filter(d => d.low !== null && d.high !== null)
  return {
    value_low:  present.reduce((a, d) => a + (d.low  ?? 0), 0),
    value_high: present.reduce((a, d) => a + (d.high ?? 0), 0),
    dims_used:  present.map(d => d.id),
  }
}

Enter fullscreen mode Exit fullscreen mode

Three decisions are written there. We sum without weighting. A dimension not yet instrumented doesn't break the calculation — it steps aside and that's noted. The caller always knows which dimensions participated, which makes every snapshot auditable three months later.

The over-addition trap

This is the most delicate technical passage of the model, and I didn't see it at first. A historicized contact contributes both to the data patrimony (dimension 3) and to the replacement cost of a CRM SaaS (dimension 1). Without correction, the same asset gets counted twice. It took me a week to understand that my intervals were inflating because I was doing exactly the error that a naive sum allows.

The fix sits in a column scope_couvert_pct on the SaaS-equivalents table: each SaaS only counts for the share of the scope it would actually cover, and the share already captured by dimension 3 is subtracted. The dim.1 query, on wakeup, is this:

-- dim 1: SaaS replacement cost, with dim 3 deduplication
SELECT
  SUM(
    cout_mensuel_eur * 12
    * (scope_couvert_pct / 100.0)
    * (1 - 0.30)  -- share already captured by dim 3 (CRM data)
    * 3.9927      -- 5-year annuity NPV at 8%
  ) AS saas_centre
FROM valorisation_saas_equivalents
WHERE actif = true;

Enter fullscreen mode Exit fullscreen mode

The 1 - 0.30 didn't come from thin air. It's the estimated share of CRM scope that would already be paid once as part of the data patrimony (3,000 contacts × market unit price). It is documented, dated, revisable. Nothing is magical. Everything is justifiable.

The weekly rerun

A valuation model that lives in a spreadsheet won't hold a quarter. So I put the calculation in a weekly cron that does three things at 4 AM on Monday:

// app/api/cron/compute-valorisation-donnees/route.ts (excerpt)
const centre =
  (contacts + leads + inscriptions) * PRIX_UNITAIRE_CONTACT_EUR +
  ANNEES_HISTORIQUE_FINANCE * VALEUR_ANNEE_HISTORIQUE_EUR +
  adrsCount * VALEUR_ADR_EUR

const donnees_low  = Math.round(centre * 0.75)
const donnees_high = Math.round(centre * 1.25)

await admin.from('valorisation_snapshots').upsert({
  snapshot_date: today,
  donnees_low, donnees_high,
  saas_low, saas_high,
  usage_low, usage_high,
  strategique_low, strategique_high,
  value_low:  sumLow,
  value_high: sumHigh,
}, { onConflict: 'snapshot_date' })

Enter fullscreen mode Exit fullscreen mode

The cron counts contacts, leads and enrollments live on Supabase, recomputes dim 3, re-reads dims 1, 2 and 4 (less volatile), sums the four, and writes a dated snapshot. Each snapshot is a defensible point. Rembrandt's value on April 14th is a row in my database; the one on April 21st will be another row, with its own explanation. You can go back, compare, explain breaks.

Four limits to accept

Dimension 4 is opinion-driven. Scored 1–10 on four axes, with written justification. Subjective, and displayed as such. The fix: frame the assumptions explicitly, date each score, force a quarterly review.

Dimension 2 has an optimistic bias. Quarterly self-reporting by Françoise, Hélène, Catherine, Claire remains imperfect. It's corrected by trend, not point by point.

The frame imposes a maintenance cost. Hour entries, revision of reference SaaS prices, update of strategic scoring, re-reading of the scope_couvert_pct of each SaaS. One to two hours per quarter, no more. That's the price of defensibility.

Dim. 1 can drift with the SaaS market. A competitor dropping its price, an open-source tool gaining maturity, and the valorisation_saas_equivalents table silently goes stale. The guardrail is human: annual review, dated notes in each row.

The conversation with Étienne

I needed a contradicting voice, and I had the right one on hand. Étienne Brossard is my majority partner — sixty percent of Palissy. During the week, he works at an investment fund that buys software publishers. His daily professional thesis is precisely to put a price on software assets whose sellers would prefer he put a different one. When he looks at a valuation table, he doesn't read it as an accountant — he reads it as an acquirer.

We met one Saturday morning at a café halfway between our two offices. I pulled up the four-dimension table on my laptop. He looked at it for thirty seconds without touching his coffee, then asked his first question, the one he always asks. « Sur quoi c'est calé, la dimension 1 ? »What is dimension 1 grounded on? I replied with the source: the valorisation_saas_equivalents table, eleven rows, public prices refreshed in March, documented scope_couvert_pct column. Nod. He moved to dimension 3. I cited the Monday 4 AM cron, the direct Supabase counts, the constant PRIX_UNITAIRE_CONTACT_EUR. Nod.

Dimension 2 stopped him longer. « Comment tu chiffres les heures ? »How do you count the hours? I explained the quarterly self-reporting, four people, loaded hourly cost reconstituted from the average payslip. « Défendable si tu affiches la méthode. Pas si tu affiches le chiffre seul. Une auto-déclaration sans cadre, c'est ce qui fait sauter une transaction en data room. »Defensible if you show the method. Not if you only show the number. An ungated self-report is what kills a deal in a data room. On dimension 4, he was quicker. « Ça c'est de l'opinion, pas du chiffre. Affiche-le comme tel, et ça tient. Si tu déguises ça en multiple, on te démonte en quinze minutes. »That's opinion, not a figure. Show it as such, and it holds. If you dress it up as a multiple, you get torn apart in fifteen minutes.

Then he closed his notebook and said the line I wanted to hear, without my reaching for it. « Il faut bien chorégraphier pour éviter les frictions financières. »You have to choreograph well to avoid financial frictions. « What you're showing me here, I've seen at fifteen companies this quarter. Three survived their due diligence. You have one advantage over the others: you wrote your model before anyone asked you for it. »

What mattered in that conversation wasn't that Étienne validated the table. It was that he could ask the same question four times — the question he asks every week to founders trying to sell him their company — and receive four answers that held. He wasn't evaluating a module. He was evaluating, under his breath, what he had bought when he came onto my cap table.

What counts isn't the correctness of the model

A valuation model is not true or false. It is defensible or it is not. The four dimensions are defensible because each can stand independently before an accountant, a buyer, or an auditor. The sum is defensible because it assumes its status as an explicit convention rather than hiding it behind a supposedly objective figure.

The most important pivot, therefore, is not moving from one dimension to four. It is accepting that any valuation of a software asset is a construction, and that a well-documented construction, with its fragilities named and its code versioned, weighs more in a discussion than a mechanically-looking calculation that hides its assumptions.

For anyone coding with an AI and wondering how to talk about the value of their work, the real question isn't "how much is it worth". It's "across how many distinct regimes of value am I prepared to defend the number I put forward". With one, we get torn apart by the first serious critic. With four, independently argued and honestly summed, we stand a chance.


What you can copy into your project

Four directly reusable elements, in order of implementation ease:

  1. The consolidate(dims) function (twelve TS lines) — sums without weighting, null-safe, tracks which dimensions were used in each calculation
  2. The scope_couvert_pct pattern — each value source declares explicitly what percentage of the scope it covers, which makes deduplication mechanical rather than eyeballed
  3. The valorisation_snapshots schema with snapshot_date UNIQUE — one dated point per week, auditable later
  4. The weekly cron that aggregates contacts/leads/enrollments live and writes Monday morning's snapshot

And one rule: any aggregated valuation is a convention, never a fact. Own it in your dashboard (visible methodology note), document every assumption, date every score. An honest model with named fragilities weighs more than a precise number that hides its assumptions.

And you — which dimensions are missing from your current measure? I read the comments.


This article is part of a series on building a 91,000-line ERP in four weeks with Claude Code for L'Atelier Palissy, an art school. The previous article explained why I abandoned the "lines × day-rate" method. The next one will detail the instrumentation trajectory of the /admin/valorisation module in three waves (schema migration, UI overhaul, monthly cron).


Companion code: rembrandt-samples/valorisation/ — the consolidate(dims) pattern, the schema, and the LOC guardrail, MIT, copy-pastable.