Apply Sir Dave Brailsford’s “aggregation of marginal gains” to your Jamf Pro Extension Attributes

Aggregation of Marginal Gains
Sir Dave Brailsford, the former performance director of British Cycling, popularized the “aggregation of marginal gains.”
This philosophy focuses on making small, incremental improvements — often as little as one percent — across every aspect of a process, which, when combined, can lead to significant overall performance enhancements.

Brailsford applied this strategy to transform British Cycling from a historically mediocre team into a dominant force, achieving remarkable success, including 7 out of 10 track cycling gold medals at the 2008 Beijing Olympics, a repeat performance at the 2012 London Olympics, and multiple Tour de France victories.
Brailsford’s philosophy emphasizes that the cumulative effect of these minor changes compounds over time, leading to extraordinary results.
He noted, “If you improve by 1% every day for a year, your performance will improve by a factor of 37 times.” ![]()
Extension Attribute Overview
Computer Extension Attributes — which allow a Jamf Pro Admin to collect extra inventory information — are one of my favorite features of Jamf Pro.
Using the Script input type, almost any client-side setting can be collected and acted upon.
- Collect Extra Information
- Text field
- Pop-up menu
- Script
- Directory Service
attribute mapping
Here’s a link to Steve’s and Lee’s Extension Attribute session from last year:
JNUC 2024: A Year with Extension Attributes – An Admin’s Journey
Establishing Your Baseline
Our first step is to establish a baseline for how long our Extension Attributes currently take to execute.
Terminal
Let’s look at a demo of using the time command in the macOS Terminal on a fully enrolled, virtual machine.
When you prepend a command with
timein macOS Terminal, the reported “total” represents the total wall-clock time taken to execute the command.This is the elapsed time from the moment the command starts until it completes, including all system and user CPU time, as well as time spent waiting for I/O, scheduling, or other system activities.
In a previously elevated Terminal window, we’ll enter time sleep 2 as a simple example of preceding commands with time. The value before the word “total” is what we’ll want to capture.
Let’s now check the actual execution time of an inventory update, via time jamf recon. Again, the value before the word “total” is what you’ll want to capture.
Self Service
Let’s look at a demo of using Self Service to establish our baseline. (We call Self Service the Workforce App Store.)
Execution time for an Inventory Update can be displayed to the end-user with the use of a custom script and duration is also available in the Jamf Pro policy log.
Here’s a link to last year’s JNUC presentation on “User-friendly Inventory Updates.”
Conducting Your Audit
Here’s a link to the GitHub repository we’ll be using; let’s look at some demos of how to use the EA Audit scripts.
EA-Download.zsh
Our first demo is leveraging the EA-Download.zsh script. We’ll start by visiting GitHub and downloading the actual script.
In the Finder, we’ll create a dedicated “EA Audit” folder and option-drag the script to create a copy.
Let’s review the script in VS Code. We’ll change logLevel to “DEBUG” then save the changes.
While we do have a previously elevated Terminal window, we’ll open a new tab in Terminal, then enter zsh EA Download.zsh help. Here we can see the commands to add the Jamf Pro API credentials to our login Keychain.
We’ll switch to Jamf Pro and in Settings, we’ll create an API role and client; looks like we need the “Read Computer Extension Attributes” privilege.
First, we’ll save the API Role and then create the API Client. Next, we’ll generate the client secret. After that, we’ll copy the credentials and head over to VS Code. In VS Code, we’ll let it know that we’re working with a snippet of JSON, increase the font size, and enable Word Wrap.
Back in Terminal, we can copy-pasta the entire first line. With the next two lines, we’ll have to copy-paste the start of what’s displayed in Terminal with the end of what’s displayed in VS Code.
OK! With the credentials stored in our Keychain, we’re ready to test! Wow! That was fast!
We have a timestamped directory with the raw JSON and a log file, and a “scripts” directory with the actual EAs.
EA-Execute.zsh
Here’s Take 2 of leveraging the “EA-Execute” script — this time on physical hardware — to better match reality.
We’re on a new Mac, so we’ll need to start from scratch, but this will give us a chance to review how to get set up … in double-time!
We’ll start by creating a working directory, which I like to call “EA Audit.”
Visiting GitHub, we’ll first download the “EA-Download” script and option-drag to our working directory.
In Terminal, even though we’ve previously elevated to root, we’ll want to create a new Terminal window for our account to properly store the Keychain entries.
Oh, that’s right! We need to include “help” for first-time set up.
In Jamf Pro, let’s rotate our API credentials — which will break the configuration on our VM — but I don’t care. We’ll then configure our Keychain entries as before.
Alright! We’re up and running again. Let’s trash the timestamped directories from our first two attempts.
With the EA scripts downloaded client-side, let’s grab the “EA-Execute” script from GitHub.
We’ll again option-drag to our working directory and run it. D-OH! Again with the root!
We’ll switch to our previously elevated Terminal window … double-D-OH! We need to supply the path to the scripts directory. Victory!
I can already feel the SSID EA needs some optimization. Yeah, the SSID EA is taking more than five times as long as the next longest EA.
Pending Updates
Let’s look at a demo of optimizing a single Extension Attribute, which has a fairly high execution time.
In Jamf Pro, we’ll look at our list of Extension Attributes and the recent addition of “Pending Software Updates.” We’ll note that it’s being displayed in the “Operating System” section of our computer inventory.
We’ll then observe that this Mac has a pending software update for macOS Tahoe 26, Beta 3; useful information, but it’s just adding too much time to each inventory update.
Since this is a recently added EA, let’s download and execute a fresh copy — there’s the SSID EA we still need to work on — and, yes, the Pending Software Update EA does feel slow when compared to the others.
Reviewing the “Execution Summary,” we can see our new EA is also the slowest of the bunch. Let’s take a closer look in VS Code.
Looks like we have a line of code commented-out just for this demo; let’s focus on that.
In our elevated Terminal window, let’s check the output of /usr/libexec/PlistBuddy -c "Print :RecommendedUpdates:" /Library/Preferences/com.apple.SoftwareUpdate.plist
Returning to VS Code, let’s un-comment the three commented-out lines and re-execute.
Not much of an improvement, but there is an actual pending update. Let’s employ some more movie-magic and update the OS in a blink of an eye! Cool new desktop in Beta 3!
In a previously elevated Terminal window, let’s re-run our PlistBuddy command; no pending updates!
Let’s time the softwareupdate binary; still more than five seconds.
Let’s re-re-execute our EA scripts — there’s that blasted SSID EA yet again — wow! This time, when there aren’t any pending software updates, our script took three-hundredths of a second to execute.
So, that was a demo of optimizing a single Extension Attribute which had a fairly high execution time by first referencing a separate — seemingly unrelated — client-side .plist.
SSID
OK! We’ve ignored the SSID EA just long enough.
This demo involves leveraging an additional, custom, “EA Frequency” code-wrapper to control how often time-intensive Extension Attribute code is actually executed. Once you get it working on one EA, it’s easy-as-pie to quickly optimize your other time-intensive EAs.
We’ll start by opening our entire “EA Audit” folder in VS Code and review the “Execution Summary” section of the log file.
Here we indeed see that the SSID EA takes more than five times as long to execute as the next longest EA. Let’s drill-in to the actual code.
Here we see we’re leveraging the generally time-consuming system_profiler binary, but it works on this beta of macOS Tahoe. Copy-pasta the snippet and proceed it with time and we’ve confirmed that this command is the culprit.
Let’s un-comment the commented-out code to enable the “EA Frequency” code-wrapper, add a sprinkle of movie-magic and we have an elevated Terminal session. We’ll start with the now-familiar time command and then VS Code’s “Run Active File.”
The first time through, we’re not seeing any performance improvement, which is to be expected. On a subsequent run, however we observe a significant improvement.
So, that was a demo of modifying the Extension Attribute code to leverage an additional, custom, “EA Frequency” code-wrapper, which controls how often time-intensive Extension Attribute code is actually executed.
Findings
Once you’ve identified the Extension Attributes with the greatest execution time, look at fine-tuning your code.
You’ll most likely discover this is more art than science and the Mac Admins Slack #scripting channel is a great place to brainstorm, or, if you’d a tad too embarrassed to publicly share your budding scripting skills, try the AI route.
A word of caution: In my experience, AI isn’t currently capable of “connecting the dots” and you may find yourself going further and further down a dead-end rabbit hole with AI, when you — as a reasoning individual — just need to reset and ensure you’re seeing the individual trees which make up the beautiful forest
If you have an EA which doesn’t need to be executed with each and every inventory update, give the EA Frequency code-wrapper a try.
Also, please be aware that script Extension Attributes can be temporarily disabled with a few clicks, while maintaining their latest data. If, after a week of having an EA disabled, you may find that you can simply delete it altogether.
Finally, we’ve been looking at EA execution times in a vacuum; you’re going to realize these gains across your entire fleet … at least twice a day … every day. Do you manage a few hundred Macs or several thousand? There are some big, big wins to be had from a couple of afternoon’s worth of work.
Dog Food
While polishing the first “official” 1.0.0 version of the EA Audit scripts, I thought it made sense to eat my own dog food (as it were) and conduct a fresh audit of our Stage lane and Production lane Extension Attributes.
I was extremely pleased with the results.


APNs Health
time zsh 143-APNs_Health.sh security: SecKeychainSearchCopyNext: The specified item could not be found in the keychain. <result>2025-10-01 08:49:20</result> zsh 143-APNs_Health.sh 17.62s user 0.63s system 79% cpu 22.820 total time zsh 'APNs Check EA (0.0.1).zsh' <result>2025-10-01 08:49:20</result> zsh 9.58s user 0.40s system 78% cpu 12.664 total time zsh 'APNs Check EA (0.0.2).zsh' <result>2025-10-01 08:49:20</result> zsh 0.02s user 0.03s system 50% cpu 0.094 total Improvement Factor: 22.820 / 12.664 = 1.8x Improvement Factor: 12.664 / 0.094 = 135x Improvement Factor: 22.820 / 0.094 = 243x
#!/bin/zsh
####################################################################################################
#
# ABOUT
#
# A Jamf Pro Extension Attribute which determines the most recent date of the
# "com.apple.ManagedClient" service.
#
####################################################################################################
#
# HISTORY
#
# Version 0.0.1, 01-Oct-2025, Dan K. Snelson (@dan-snelson)
# Original version (inspired by https://mann.com/jamf)
#
# Version 0.0.2, 01-Oct-2025, Dan K. Snelson (@dan-snelson)
# Added Extension Attribute Frequency
#
####################################################################################################
####################################################################################################
#
# Variables
#
####################################################################################################
scriptVersion="0.0.2"
export PATH=/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin/
####################################################################################################
#
# Extension Attribute Frequency
#
####################################################################################################
# Import client-side functions
source /path/to/your/client-side/functions.sh
# Name of Extension Attribute
eaName="APNs Check"
# Number of days between executions
eaDays="7"
####################################################################################################
#
# Program
#
####################################################################################################
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# Determine the most recent date of the "com.apple.ManagedClient" service
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
eaFrequency "${eaName}" "${eaDays}"
if [[ "${eaExecution}" == "Yes" ]]; then
apnsCheck=$( command log show --last 24h --predicate 'subsystem == "com.apple.ManagedClient" && (eventMessage CONTAINS[c] "Received HTTP response (200) [Acknowledged" || eventMessage CONTAINS[c] "Received HTTP response (200) [NotNow")' | tail -1 | cut -d '.' -f 1 )
if [[ "${apnsCheck}" == *"Timestamp"* ]] || [[ -z "${apnsCheck}" ]]; then
result="2000-01-01 00:00:01"
else
result="${apnsCheck}"
fi
eaResult "${eaName}" "${result}"
else
eaResult "${eaName}"
fi
jssLog "<result>${returnedResult}</result>"
exit 0
Pending Software Updates
time zsh 57-Pending_Software_Updates.sh
Dict {
Identifier = MSU_UPDATE_25A362_patch_26.0.1_major
Display Name = macOS Tahoe 26.0.1
MobileSoftwareUpdate = true
Product Key = MSU_UPDATE_25A362_patch_26.0.1_major
Display Version = 26.0.1
}
<result>macOS Tahoe 26.0.1-25A362</result>
zsh 57-Pending_Software_Updates.sh 0.03s user 0.03s system 1% cpu 5.441 total
time zsh 'Pending Software Updates (0.0.3).zsh'
<result>macOS Tahoe 26.0.1</result>
zsh 0.01s user 0.02s system 54% cpu 0.035 total
Improvement Factor: 5.441 / 0.035 = 155x
#!/bin/zsh --no-rcs
# shellcheck shell=bash
####################################################################################################
#
# ABOUT
#
# Pending Software Updates Extension Attribute
#
####################################################################################################
#
# HISTORY
#
# Version 0.0.1, 14-Aug-2024, Dan K. Snelson (@dan-snelson)
# Based on: Software Update Deferrals (1.4.0).sh
#
# Version 0.0.2, 11-Apr-2025, Dan K. Snelson (@dan-snelson)
# Updated for macOS 15.4
#
# Version 0.0.3, 01-Oct-2025, Dan K. Snelson (@dan-snelson)
# Updated to use only "/Library/Preferences/com.apple.SoftwareUpdate.plist"
#
####################################################################################################
####################################################################################################
#
# Variables
#
####################################################################################################
scriptVersion="0.0.3"
export PATH=/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin/
recommendedUpdates=$( /usr/libexec/PlistBuddy -c "Print :RecommendedUpdates:" /Library/Preferences/com.apple.SoftwareUpdate.plist 2>/dev/null )
displayNames=$( echo "$recommendedUpdates" | grep '^ *Display Name = ' | cut -d= -f2- | sed 's/^[[:space:]]*//;s/[[:space:]]*$//' )
displayNames=$( echo "$displayNames" | grep . )
####################################################################################################
#
# Program
#
####################################################################################################
if [[ -z "$displayNames" ]]; then
echo "<result>None</result>"
else
displayNamesArray=("${(@f)displayNames}")
joinedNames=""
first=true
for name in "${displayNamesArray[@]}"; do
if [[ "$first" == true ]]; then
joinedNames="$name"
first=false
else
joinedNames="${joinedNames}; $name"
fi
done
echo "<result>$joinedNames</result>"
fi
exit 0
SSID
Determining a Mac’s SSID (like an animal) > Update: September 2025
Pingback:Jamf Pro Performance Tuning: Extension Attribute Audit - Dan K. Snelson