Add a data source using Coldfusion Administrator API

Mike's Notes

Google Search - AI Mode (Gemini) was used to find the sample code for adding a data source using the ColdFusion Administrator API.

Speed is king

My strength is architecture and problem-solving, not coding (slow writer and too many typos), so 99.9% of the coding is now supplied via Google Search - AI Mode (Gemini). Then I test everything. About 100X faster. 😎😎😎😎😎😎😎

Data sources

data/

  • couchbase/
  • db2/
  • derby/
  • h2/
  • hsqldb/
  • mariadb/
  • msaccess/
    • 32/ (32-bit)
    • 64/ (64-bit)
  • mssql/
  • oracle/
  • pg/
    • 18/ (version 18)
  • sqllite/
  • sybase/
  • virtuoso/

Other issues to explore later

  • The advanced arguments (such as connection pool limits or timeout settings) for these specific drivers.

Future testing

  • Install loki-01 on 9cc/
  • Run the Data Engine (dat) to create all data sources
  • Test data sources.

Here is a detailed example copied from the ColdFusion Cookbook. It is written by Jeremy Petersen and was last updated in 2007.


How do I programmatically create a new datasource?

The short answer is to use the ColdFusion Administrator API.


The following is taken directly from the ColdFusion documentation:
You can perform most ColdFusion MX Administrator tasks programmatically using the Administrator API. The Administrator API consists of a set of ColdFusion components (CFCs) that contain methods you call to perform Administrator tasks. For example, you use the setMSQL method of datasource.cfc to add a SQL Server data source.

<cfscript>
   // Login is always required. This example uses a single line of code.
   createObject("component","cfide.adminapi.administrator").login("admin");
   // Instantiate the data source object.
   myObj = createObject("component","cfide.adminapi.datasource");
   // Required arguments for a data source.
   stDSN = structNew();
   stDSN.driver = "MSSQLServer";
   stDSN.name="northwind_MSSQL";
   stDSN.host = "10.1.147.73";
   stDSN.port = "1433";
   stDSN.database = "northwind";
   stDSN.username = "sa";
   // Optional and advanced arguments.
   stDSN.login_timeout = "29";
   stDSN.timeout = "23";
   stDSN.interval = 6;
   stDSN.buffer = "64000";
   stDSN.blob_buffer = "64000";
   stDSN.setStringParameterAsUnicode = "false";
   stDSN.description = "Northwind SQL Server";
   stDSN.pooling = true;
   stDSN.maxpooledstatements = 999;
   stDSN.enableMaxConnections = "true";
   stDSN.maxConnections = "299";
   stDSN.enable_clob = true;
   stDSN.enable_blob = true;
   stDSN.disable = false;
   stDSN.storedProc = true;
   stDSN.alter = false;
   stDSN.grant = true;
   stDSN.select = true;
   stDSN.update = true;
   stDSN.create = true;
   stDSN.delete = true;
   stDSN.drop = false;
   stDSN.revoke = false;
   //Create a DSN.
   myObj.setMSSQL(argumentCollection=stDSN);
</cfscript>

Resources

References

  • Reference

Repository

  • Home > Ajabbi Research > Library >
  • Home > Handbook > 

Last Updated

18/04/2026

Add a data source using Coldfusion Administrator API

By: Mike Peters and Gemini
On a Sandy Beach: 18/04/2026

Mike is the inventor and architect of Pipi and the founder of Ajabbi.

Google Gemini is cool.

The ColdFusion server stores data source configurations in specific XML files located within its installation directory. The exact location depends on your version and installation type (Server vs. J2EE configuration). [1, 2, 3, 4, 5] 

Configuration File Locations

Most modern Adobe ColdFusion versions (including ColdFusion 2021 and 2025) store these settings in the following files:

  • Main Datasource File: neo-datasource.xml.
  • Legacy/Alternative File: neo-query.xml (often used in older versions like ColdFusion 7). [1, 2] 

Default File Paths

The absolute path varies based on how ColdFusion was installed: [6] 

  • Server Configuration (Standard): {cf_root}/cfusion/lib/ (e.g., C:\ColdFusion2021\cfusion\lib\neo-datasource.xml on Windows).
  • JEE / Multiserver Configuration: {cf_webapp_root}/WEB-INF/cfusion/lib/.
  • Central Config Server (CCS): If using a [Central Config Server](https://helpx.adobe.com/coldfusion/using/central-config-server-coldfusion.html), settings are stored in <CF_Instance_Home>/bin/ccsstore/ and replicated across nodes. [1, 2, 3, 7] 

Important Notes

  • Encryption: While you can see the DSN names and server addresses in these XML files, passwords are encrypted and cannot be read in plain text.
  • Editing: It is highly recommended to manage datasources through the ColdFusion Administrator (found under Data & Services > Data Sources) rather than editing the XML files directly to avoid corruption.
  • API Access: You can also manage these settings programmatically using the [ColdFusion Administrator API](https://helpx.adobe.com/coldfusion/kb/database-connections-handled-coldfusion.html). [1, 8, 9, 10, 11, 12] 

References

To use the ColdFusion Administrator API to add a datasource, you use a set of ColdFusion components (CFCs) located in the /CFIDE/adminapi/ directory. This allows you to manage server settings programmatically without using the web-based Administrator interface. [1, 2, 3, 4] 

Prerequisites

  • Enable RDS: Some versions or configurations may require enabling the RDS service in Security > RDS within the ColdFusion Administrator.
  • Administrator Password: You must have the server's administrator password to authenticate. [1, 5, 6, 7] 

Basic Steps and Example Code

The following cfscript example demonstrates how to log in and create a Microsoft SQL Server datasource using the datasource.cfc (or Data Sources.cfc in some versions). [5, 8] 

<cfscript>
    // 1. Authenticate with the Administrator API
    adminObj = createObject("component", "cfide.adminapi.administrator");
    adminObj.login("yourAdminPassword"); // Replace with your actual admin password
    // 2. Instantiate the Data Source object
    // Note: Use "datasource" or "Data Sources" depending on your CF version
    dsObj = createObject("component", "cfide.adminapi.datasource");
    // 3. Define the datasource details
    // For SQL Server, you use the setMSSQL method
    dsObj.setMSSQL(
        name = "MyNewDSN",
        host = "127.0.0.1",
        port = "1433",
        database = "MyDatabaseName",
        username = "dbUser",
        password = "dbPassword",
        description = "Datasource created via Admin API"
    );
    // 4. (Optional) Verify the connection
    isVerified = dsObj.verifyDsn("MyNewDSN");
    
    if (isVerified) {
        writeOutput("Datasource successfully created and verified!");
    } else {
        writeOutput("Datasource created but failed verification.");
    }
</cfscript>

Common Methods for Different Drivers

The datasource component provides specific methods for different database types: [4, 9, 10] 

  • SQL Server: setMSSQL()
  • MySQL: setMySQL5() or setMySQL()
  • [Oracle](https://www.oracle.com/): setOracle()
  • Derby: setDerbyEmbedded()
  • Other JDBC: setOther() (used for custom or thin drivers) [4, 5, 6, 8, 11, 12, 13] 

Alternative: Per-Application Datasources [14] 

In ColdFusion 2021 and later, you can also define datasources directly in your Application.cfc without using the Admin API. This is often preferred for modern application deployment as it keeps configurations within the application code. [14, 15, 16, 17, 18]

// In Application.cfc
component {
    this.name = "MyApplication";
    this.datasources["myDSN"] = {
        driver: "MSSQLServer",
        host: "localhost",
        database: "mydb",
        username: "user",
        password: "pass"
    };
    this.datasource = "myDSN";
}

References

To use the ColdFusion Administrator API with tag-based syntax, you must first authenticate using administrator.cfc, then call the specific driver methods in datasource.cfc.

1. Authentication (Required First)

Before adding any datasource, you must log in to the API session. [1] 

<cfset adminObj = createObject("component", "cfide.adminapi.administrator")>
<cfset adminObj.login("yourAdminPassword")>
<!--- Instantiate the datasource object for subsequent calls --->
<cfset dsObj = createObject("component", "cfide.adminapi.datasource")>

------------------------------

2. Database-Specific Tag Examples

Microsoft SQL Server

Uses the setMSSQL method.

<cfset dsObj.setMSSQL(
    name = "MyMSSQL_DSN",
    host = "127.0.0.1",
    database = "Northwind",
    username = "db_user",
    password = "db_password"
)>

PostgreSQL

Uses the setPostgreSQL method.

<cfset dsObj.setPostgreSQL(
    name = "MyPostgres_DSN",
    host = "localhost",
    database = "sales_db",
    username = "postgres",
    password = "password"
)>

MySQL

Uses setMySQL5 (for MySQL 5.x and later, including MariaDB).

<cfset dsObj.setMySQL5(
    name = "MyMySQL_DSN",
    host = "://example.com",
    database = "inventory",
    username = "admin",
    password = "secretpassword"
)>

Oracle

Uses setOracle. Note that Standard edition users often use the "Other" method with an Oracle thin driver.

<cfset dsObj.setOracle(
    name = "MyOracle_DSN",
    host = "oracle_server",
    service_name = "ORCL",
    username = "system",
    password = "password"
)>

MS Access (32-bit vs. 64-bit)

Both use the setMSAccess method, but the behaviour depends on the server's ODBC configuration and the ColdFusion bitness.

  • 32-bit: Requires the 32-bit Microsoft Access Database Engine.
  • 64-bit: Requires the 64-bit Microsoft Access Database Engine.

<cfset dsObj.setMSAccess(
    name = "MyAccessDSN",
    database = "C:\data\mydb.mdb"
)>

Sybase

Uses the setSybase method.

<cfset dsObj.setSybase(
    name = "MySybase_DSN",
    host = "sybase_host",
    database = "production",
    username = "sa",
    password = "password"
)>

DB2

Uses the setDB2 method.

<cfset dsObj.setDB2(
    name = "MyDB2_DSN",
    host = "db2_server",
    database = "SAMPLE",
    username = "db2admin",
    password = "password"
)>

------------------------------

3. Verification (Recommended)

After adding a datasource, it is best practice to verify the connection immediately.

<cfset isVerified = dsObj.verifyDsn("MyMSSQL_DSN")>
<cfif isVerified>
    <p>Connection Successful!</p>
<cfelse>
    <p>Connection Failed. Check credentials or server availability.</p>
</cfif>

References

Java System getProperties() Method

Mike's Notes

In the Pipi Nest, I'm using CFML to retrieve Java properties directly from Java.

Test code

Here is some test code, tried yesterday. There are other ways as well.

 <!--- Instantiate the java.lang.System class --->
    <cfset system = createObject("java", "java.lang.System")>

<!--- Retrieve additional JVM properties --->
    <cfset javaVersion = system.getProperty("java.version")>
    <cfset javaVendor = system.getProperty("java.vendor")>
    <cfset javaClassPath = system.getProperty("java.class.path")>
    <cfset javaHome = system.getProperty("java.home")>
  
    <cfoutput>
      <ul>
          <li><strong>Vendor:</strong> #javaVendor#</li>
          <li><strong>Version:</strong> #javaVersion#</li>
          <li><strong>Home:</strong> #javaHome#</li>
          <li><strong>Classpath:</strong> #javaClassPath#</li>
      </ul>
    </cfoutput>

Resources

References

  • Reference

Repository

  • Home > Ajabbi Research > Library >
  • Home > Handbook > 

Last Updated

17/04/2026

Java System getProperties() Method

By: 
Tutorials Point: 17/04/2026

Tutorials Point originated from the idea that there exists a class of readers who respond better to online content and prefer to learn new skills at their own pace from the comforts of their drawing rooms.

Our mission is to deliver Simply Easy Learning with clear, crisp, and to-the-point content on a wide range of technical and non-technical subjects without any preconditions and impediments.

Description

The Java System getProperties() method determines the current system properties. The current set of system properties for use by the getProperty(String) method is returned as a Properties object.

If there is no current set of system properties, a set of system properties is first created and initialised. This set of system properties includes values for the following keys −


Key Description of Associated Value
java.version Java Runtime Environment version
java.vendor Java Runtime Environment vendor
java.vendor.url Java vendor URL
java.home Java installation directory
java.vm.specification.version Java Virtual Machine specification version
java.vm.specification.vendor Java Virtual Machine specification vendor
java.vm.specification.name Java Virtual Machine specification name
java.vm.version Java Virtual Machine implementation version
java.vm.vendor Java Virtual Machine implementation vendor
java.vm.name Java Virtual Machine implementation name
java.specification.version Java Runtime Environment specification version
java.specification.vendor Java Runtime Environment specification vendor
java.specification.name Java Runtime Environment specification name
java.class.version Java class format version number
java.class.path Java class path
java.library.path List of paths to search when loading libraries
java.io.tmpdir Default temp file path
java.compiler Name of JIT compiler to use
java.ext.dirs Path of extension directory or directories
os.name Operating system name
os.arch Operating system architecture
os.version Operating system version
file.separator File separator ("/" on UNIX)
path.separator Path separator (":" on UNIX)
line.separator Line separator ("\n" on UNIX)
user.name User's account name
user.home User's home directory
user.dir User's current working directory

Declaration

Following is the declaration for java.lang.System.getProperties() method

public static Properties getProperties()

Parameters

NA

Return Value

This method returns the system properties.

Exception

SecurityException − if a security manager exists and its checkPermission method doesn't allow access to the process environment.

Example: Getting All Available Properties of JVM System

The following example shows the usage of Java System getProperties() method. We've retrieved a Properties object using System.getProperties() method. Then using list() method of Properties object, we're printing all properties on console.

package com.tutorialspoint;

import java.util.Properties;

public class SystemDemo {

   public static void main(String[] args) {

      // this will list the current system properties
      Properties p = System.getProperties();
      p.list(System.out);
   }

Output

Let us compile and run the above program, this will produce the following result −

package com.tutorialspoint;

import java.util.Properties;

public class SystemDemo {

   public static void main(String[] args) {

      // this will list the current system properties
      Properties p = System.getProperties();
      p.list(System.out);
   }

Output

-- listing properties --
java.specification.version=21
sun.cpu.isalist=amd64
sun.jnu.encoding=Cp1252
java.class.path=C:\Users\Tutorialspoint\eclipse-works...
java.vm.vendor=Oracle Corporation
sun.arch.data.model=64
user.variant=
java.vendor.url=https://java.oracle.com/
java.vm.specification.version=21
os.name=Windows 11
sun.java.launcher=SUN_STANDARD
user.country=IN
sun.boot.library.path=C:\Program Files\Java\jdk-21\bin
sun.java.command=com.tutorialspoint.SystemDemo
jdk.debug=release
sun.cpu.endian=little
user.home=C:\Users\Tutorialspoint
user.language=en
java.specification.vendor=Oracle Corporation
java.version.date=2024-01-16
java.home=C:\Program Files\Java\jdk-21
file.separator=\
java.vm.compressedOopsMode=Zero based
line.separator=

java.vm.specification.vendor=Oracle Corporation
java.specification.name=Java Platform API Specification
user.script=
sun.management.compiler=HotSpot 64-Bit Tiered Compilers
java.runtime.version=21.0.2+13-LTS-58
user.name=Tutorialspoint
stdout.encoding=UTF-8
path.separator=;
os.version=10.0
java.runtime.name=Java(TM) SE Runtime Environment
file.encoding=UTF-8
java.vm.name=Java HotSpot(TM) 64-Bit Server VM
java.vendor.url.bug=https://bugreport.java.com/bugreport/
java.io.tmpdir=C:\Users\TUTORI~1\AppData\Local\Temp\
java.version=21.0.2
user.dir=C:\Users\Tutorialspoint\eclipse-works...
os.arch=amd64
java.vm.specification.name=Java Virtual Machine Specification
sun.os.patch.level=
native.encoding=Cp1252
java.library.path=C:\Program Files\Java\jdk-21\bin;C:\W...
java.vm.info=mixed mode, sharing
stderr.encoding=UTF-8
java.vendor=Oracle Corporation
java.vm.version=21.0.2+13-LTS-58
sun.io.unicode.encoding=UnicodeLittle
java.class.version=65.0

Official Trailer for The Dyslexic Advantage Movie

Mike's Notes

I'm very lucky, and so are these people. Grammarly is just a tool. Work from what you are good at.

Mind Strengths Assessment

I did the assessment. This is my score.

You can also do a free assessment.

Resources

References

  • The Dyslexic Advantage: Unlocking the Hidden Potential of the Dyslexic Brain, by Brock and Fernette Eide. Penguin 2012.

Repository

  • Home > Ajabbi Research > Library >
  • Home > Handbook > 

Last Updated

16/04/2026

Official Trailer for The Dyslexic Advantage Movie

By: Brock and Fernette Eide
Dyslexia Advantage: xx/10/2026

.

Pipi Nest update - what I learned this week

Mike's Notes

The experiments continue, with progress slow but steady, and with a lot of new stuff learned.

Ongoing test results at the end. This one seems to be working without error.

😎😎😎😎

Resources

References

  • Reference

Repository

  • Home > Ajabbi Research > Library >
  • Home > Handbook > 

Last Updated

17/04/2026

Pipi Nest update - what I learned this week

By: Mike Peters
On a Sandy Beach: 15/04/2026

Mike is the inventor and architect of Pipi and the founder of Ajabbi.

Problem

Last week, I created Pipi Nest, a container that uses a standard root directory convention for hosting Pipi.

  1. The problem I discovered was that a standard deployment was not working across multiple CFML Engine environments on various operating systems.
    • Adobe ColdFusion Server 11+
    • Lucee
    • BoxLang
  2. Pipi (robot version) is required to manipulate enterprise applications.
  3. Mission Control requires a website
  4. Some of the configuration files were outside the webroot.
    • Application.cfc (1), (2)

Solution

  • Install side by side in <pipi nest>/pipi/
    • <user account>/ (none, one, or many)
    • <pipi instance-n>/ (one or many)
  • <pipi nest>/pipi/<pipi instance>/www/
    • mission-control/
  • Create CFML server mappings where a Pipi Instance is the only user.
    • data/
    • pipi/
    • work/

Database support

Adobe ColdFusion, Lucee, and BoxLang are all built on the Java Virtual Machine (JVM). This means they can technically connect to any relational database that provides a JDBC (Java Database Connectivity) driver

Pipi Core example (Windows)

/9cc/ (Pipi Nest)

  • pipi_nest_probe.cfm
  • data/
    • couchbase/
    • db2/
    • derby/
    • h2/
    • hsqldb/
    • mariadb/
    • msaccess/
      • 32/
      • 64/
    • mssql/
    • oracle/
    • pg/
      • 18/
    • sqllite/
    • sybase/
    • virtuoso/
  • pipi/
      • Application.cfc (1) - Nest settings
      • pipi_nest.cfm
      • loki-01/ (instance)
        • ...
      • loki-02/ (instance)
        • Application.cfc (2) - Account settings
        • pipi_account.cfm
        • pip/
          • Application.cfc (3) - System settings
          • pipi_system.cfm
          • i18n/
          • log/
          • pipi_<pipi version>.txt
          • sys/
          • temp/
          • template/
            • _include/
            • _layout/
              • _log/
        • www/
          • mission-control/
            • Application.cfc (4) - Website settings
    • work/
      • backup/
      • install/
      • project/

    Pipi Enterprise example (Windows)

    /9ae/ (Pipi Nest)

    • pipi_nest_probe.cfm
    • data/
      • couchbase/
      • db2/
      • derby/
      • h2/
      • hsqldb/
      • mariadb/
      • msaccess/
        • 32/
        • 64/
      • mssql/
      • oracle/
      • pg/
        • 18/
      • sqllite/
      • sybase/
      • virtuoso/
    • pipi/
      • Application.cfc (1) - Nest settings
      • pipi_nest.cfm
      • ajabbi/ (Account Name)
        • Application.cfc (2) - Account settings
        • pipi_account.cfm
        • com/
        • dat/
        • lib/
        • log/
        • plu/
        • tmp/
        • www/
          • learn.ajabbi.com/
            • Application.cfc (4) - Website settings
          • wiki.ajabbi.com/
            • Application.cfc (4) - Website settings
      • dis-01/ (Instance)
      • ...
      • dis-04/ (Instance)
        • Application.cfc (2) - Account settings
        • pipi_account.cfm
        • pip/
          • Application.cfc (3) - System settings
          • pipi_system.,cfm
          • i18n/
          • log/
          • pipi_<pipi version>.txt
          • sys/
          • temp/
          • template/
            • _include/
            • _layout/
              • _log/
        • www/
          • mission-control/
            • Application.cfc (4) - Website settings
    • work/
      • backup/
        • pipi_9ae_ajabbi_pipi_www_learn.ajabbi.com_20260411.zip
      • install/
      • project/

    Automated installs

    • Adobe ColdFusion Server 11+: Many XML files store the server configuration. Any pipi instance doing Pipi Nest installs could rewrite these XML files.
    • Lucee: Yet to discover
    • BoxLang: Yet to discover

    Production obfuscation

    Pipi will obfuscate these names using UUIDs and other dastardly methods on public-facing production websites. But the names are very useful for UI labels and visualisation.

    Test Results


    NZ DateTime Action Object Status
    2026-04-15 14:15 Edit server.xml Mappings Success
    2026-04-15 14:20  Create Mapping Docs Complete
    2026-04-15 14:26  Rename Named instances Success
    2026-04-15 14:48 Create Mission Control Success
    2026-04-15 17:24 Test Application.cfc (1) - Pipi Nest settings Success
    2026-04-15 17:40 Test pipi_nest.cfm Success
    2026-04-16 13:22 Test pipi_account.cfm Success
    2026-04-16 13:54 Test Application.cfc (2) - Pipi Account settings
    Not inheriting Application.cfc (1)
    Success
    2026-04-16 15:09 Test Application.cfc (3) - Pipi System settings Success
    2026-04-16 15:40 Test pipi_system.cfm Success
    2026-04-16 16:02 Test Application.cfc (4) - Pipi Website settings Success
    2026-04-16 16:03 Test pipi_website.cfm Success
    2026-04-16 19:09 Create Named instance website Success
    2026-04-16 19:44 Test pipi_nest_probe.cfm Success
    2026-04-16 20:28 Test java.lang.System class - get properties Success
    2026-04-17 11:23 Test Add a 32-bit datasource using the CFML Engine CFIDE Success
    2026-04-17 11:56 Test Add a 64-bit datasource using the CFML Engine CFIDE Success
    2026-04-17 13:33 Test Add a datasource using Coldfusion Administrator API
    • couchbase/
    • db2/
    • derby/
    • h2/
    • hsqldb/
    • mariadb/
    • msaccess/
    • mssql/
    • oracle/
    • pg/
    • sqllite/
    • sybase/
    • virtuoso/
    Success
    2026-04-18 Test Code for Linux vs Windows path delimiters








    2026-04-19 18:00 Demo 9cc/ live demo to Open Research Group












    Claude got a new superpower

    Mike's Notes

    Note

    Resources

    References

    • Reference

    Repository

    • Home > Ajabbi Research > Library > Subscriptions > Amazing CTO
    • Home > Handbook > 

    Last Updated

    14/04/2026

    Claude got a new superpower

    By: Stephan Schmidt
    Amazing CTO: 22/03/2026

    Your CTO Coach in Germany and Europe.

    Claude got a superpower and no one recognized it.

    It’s /loop.

    You now can run a prompt every 5 minutes.

    You might think, “So what?” a way to repeat prompts. Nothing earth shattering.

    I look at this differently.

    The one thing AIs are bad at is determinism. LLMs are probability machines.

    If you ask an AI to search for bugs you get a list of bugs. If you ask the AI again, you get a different list. Doesn’t the AI know what they do? No they don’t - they are not thinking and planning engineers - they are probability machines.

    This can be fought with /loop.

    Let’s let Claude run a bug searching prompt every 10 minutes.

    /loop 10min "deep search src/ for bugs. add to potential_bugs.md"

    First run:

    • Done. Created potential_bugs.md with 12 unique potential bugs found

    Second run:

    • Found 5 new bugs (1 was a duplicate of an existing entry). Let me append them to potential_bugs.md.

    Third run:

    • The search is converging — most code paths have now been covered across 3 scans.

    Fifth run:

    • No new bugs found this scan — all 3 results were duplicates of already-known issues (#4, #17, #18). potential_bugs.md remains at 22 bugs. The codebase has been thoroughly covered across 5 scans. Further scans are unlikely to surface new findings without code changes.

    Then:

    • No new bugs found. After 6 thorough scans covering all .go files in src/ and its subdirectories, the search has converged.

    This feels a lot like the casino method of algorithms.

    The results have been converging after five runs.

    With the list, finally one would run a prompt to evaluate and verify the bugs, rank them, write tests and fix them.

    Incidentally there is an informal ‘Rule of 5’. Xuezhi Wang and the team at Google Research wrote in their 2022 paper on ‘Self-Consistency,’ running a prompt multiple times leads to better results.

    This goes way beyond bug hunting. Every analysis query that you use an AI for, finding architecture problems, security flaws, requirements from a codebase now can easily be made much more powerful.

    Just /loop !

    "Collaboration" is bullshit

    Mike's Notes

    Hell, why does this remind me of innovation theatre? 😎

    I love the writer's brutal honesty.

    Resources

    References

    • Reference

    Repository

    • Home > Ajabbi Research > Library > Subscriptions > Amazing CTO
    • Home > Handbook > 

    Last Updated

    13/04/2026

    "Collaboration" is bullshit

    By: J.A. Westenberg
    Westenberg: 22/03/2026

    I'm JA Westenberg. I publish a weekly column on technology, culture, philosophy and what it means to be a human being.

    In 1944, the Wehrmacht launched into Hitler’s last ditch effort to save the Third Reich. The Battle of the Bulge was a doomed campaign and a doomed gamble from a doomed regime, but its brutality was a true second test of the US Army on the Western Front. During the battle, Army historian S.L.A Marshall began interviewing infantry companies who’d been baptised in combat. Published 3 years later in his 1947 book, Men Against Fire, Marshall’s research showed that just 15-20% of riflemen in active combat positions ever fired their weapons - most kept their heads down. They moved when they were ordered and they held their positions, and they mimicked the outward appearance of a soldier in battle - but shoot, they did not. By any standard organisational metric, the men were present and accounted for, but 4 out of 5 never pulled the trigger. 

    You can debate the extent of Marshall’s numbers, and you can debate his methodology, but his ratio shows up, again and again. IBM stumbled onto it in the ‘60s when they discovered that 80% of computer usage came from 20% of the system’s features. The pattern recurs because it describes something real about how effort is distributed inside groups, where a fraction of the people do most of the work, and the rest provide what you might ~charitably call “structural support.”

    Anyone who has worked in any large organisation knows exactly what I’m talking about. 

    The modern tech industry looked at the problem of human coordination and participation and decided the solution was “collaboration.” If only 20% of us are operating with a “killer instinct” we need to be better at managing the shared instincts of the other 80%. And so collaboration became our shared obsession. We pursue “teamwork” as a holy grail. 

    The teamwork revolution, if you can call it that, gave us Notion for our documents, ClickUp for our tasks, Slack for our conversations, Jira for our tickets, Monday for our boards, Teams for the calls that should been emails, emails for the things that we couldn’t squeeze in anywhere else, and now agents attempting to re-invent the whole stack. The average knowledge worker maintains accounts across system after system, switching between applications hundreds of times per day. And they produce, in aggregate, a staggering amount of coordinated and collaborative activity that never actually becomes anything resembling ~output. 

    When you strip away the product marketing and the dev relations and the blog posts and the funding rounds and the fuckery-upon-fuckery of it all, we’re left with a simulation of collective engagement - but very little else. Transparency got confused with progress, visibility got confused with accountability, and being included in the thread became the same thing, socially and organizationally, as owning the outcome.

    Once that confusion set in at the cultural level it became nearly impossible to dislodge. The feeling of collaboration is pleasant in a way that personal accountability can never be. Owning something means you, specifically and visibly you, can fail at it, specifically and visibly, in ways that attach to your name.

    Collaborating means the failure belongs to the process.

    So everyone chose collaboration, and we called it culture.

    Marshall's riflemen were ordinary people responding to the diffusion of responsibility that happens inside any group. Maximilien Ringelmann measured the same phenomenon with ropes in 1913, long before there were Slack workspaces to offer an emoji-react to it. Individual effort drops predictably as group size increases. The presence of others dissolves the sense of personal responsibility in a way that feels, to everyone experiencing it, entirely reasonable. You're part of a team, you're contributing, you're also (measurably) pulling less hard than you would if the rope were yours alone. Every single person on the rope is doing this simultaneously, which is why the total force never adds up the way the headcount says it should.

    Frederick Brooks identified the same dynamic in software development in 1975, watching IBM's System/360 project illustrate his emerging thesis that adding people to a late project makes it later. Communication overhead grows faster than headcount, coordination costs compound, and every new person contributes their capacity along with their relationships to everyone else. Those relationships require maintenance and produce misalignment and generate the need for more meetings to address the misalignment those meetings created.

    Brooks might as well have described your company's Q3 roadmap planning cycle and your startup's sprint retrospective, all of which have gotten longer every year and produced, relative to their investment, less.

    The collaboration industry has spent a fortune obscuring a dirty truth: most complex, high-quality work is done by individuals or very small groups operating with clear authority and sharp accountability, then rationalized into the language of teamwork afterward. Dostoevsky wrote _The Brothers Karamazov_ alone. The Apollo Guidance Computer came from a team at MIT small enough to have real ownership, hierarchical enough that Margaret Hamilton's name could go on the error-detection routines she personally designed.

    Communication matters, and shared context matters. But there’s a huge difference between communication and collaboration as infrastructure to support individual, high-agency ownership, and communication and collaboration as the primary activity of an organisation. Which, if we’re honest, is what most collaboration-first cultures have actually built. They’ve constructed extraordinarily sophisticated machinery for the social management of work, without actually doing the work they’re socialising about. 

    If and when it exists, ownership looks like an individual who deeply gives a shit, making a call without waiting for group-consensus. That individual will be right sometimes, and they’ll be wrong other times, and they’ll own it. They won’t sit around waiting to find out who has the authority to move a card from one column to another and post about it in the #celebrations  channel. 

    But being that person sucks when “collaboration” is the reigning value, because every unilateral decision gets read as a cultural violation and a signal that you aren’t a team player. Collaboration-as-ideology has made ownership and responsibility feel antisocial, which is a hell of a thing, given that ownership is the only mechanism that gets anything across the finish line. 

    You can see this excess everywhere. Standups where people announce their busy work and as long as everyone’s “on the same page” nobody changes course. Documents that are written to perform thinking so somebody else can perform thinking, with no decision in sight. Retros, and kickoffs, and WIP meetings that spawn their own retros, kickoffs and WIP meetings like cells dividing and re-dividing, with zero connection to the work that it’s nominally organising around. 

    Every project now seems to carry more coordination overhead than execution time, and when it fails the postmortem just recommends more collaboration...

    At some point (and I think that point was fucking yesterday) we have to ask ourselves - what are we actually producing and who is actually responsible for producing it? 

    Because at some level, the answer for “who is responsible for X” has to be one single person, no matter how much the collaborative apparatus layered over modern work has been engineered to make that person invisible and dissolve accountability. 

    We need to find some path back to trusting that individuals will do their jobs, without every responsibility being visible to an entire organisation, without follow-ups being scheduled by a cadre of overpaid managers with their overfed metrics. 

    Maybe - just maybe - we could make our lives a little easier. Maybe we could let human beings keep their own lists of tasks, and we could let them sink or swim by how they manage those tasks, and we could assign blame to them and to them alone when they fuck up. Maybe we could do it without needing to have team-level views of every Kanban, calendar and task list. And maybe - if we let go of the warm, expensive fiction of collective endeavour - we could make it a little easier to see who among us are pulling the trigger and who are just keeping their heads down.