The Velocity Problem
About This Sketch
A comparison of high-velocity work versus considered-pace development. The left side shows rapid project creation with quick decay—high throughput but low durability. The right side demonstrates slower, more deliberate work that produces lasting value. This sketch accompanies the essay "The Velocity Problem" and visualizes how speed fundamentally changes the nature and longevity of what gets built.
Algorithm
This sketch visualizes the fundamental tradeoff between velocity and durability in creative work. Two workers operate at different paces, producing work with dramatically different lifecycles.
The high-velocity worker on the left rapidly produces small projects that quickly decay and crumble. Despite high throughput, most work becomes technical debt that fades away. The slower, more deliberate worker on the right builds fewer things but creates lasting value—projects that endure and compound over time.
The visualization captures how velocity optimizes for short-term output at the expense of long-term value, while considered pace produces work that maintains integrity and continues to provide value long after creation.
Pseudocode
SETUP:
Create two workers with different working styles
Initialize project tracking arrays
Set canvas to 400x300 in center-rect mode
FAST WORKER UPDATE (every frame):
Every 20 frames: Create new project at rapid pace
For each active project:
Age the project
After 100 frames: Mark as decayed (technical debt accumulates)
If decayed: Fade out and remove
If not decayed: Move upward slowly
SLOW WORKER UPDATE (every frame):
If no current project: Start new one with progress bar
Increment progress slowly (0.5 per frame)
When progress reaches 100:
Complete project and add to lasting collection
Projects rise very slowly (enduring value)
DRAW (every frame):
Clear background
Draw labels and divider
Fast worker side:
Draw worker with motion blur (rapid movement)
Draw all projects as small blocks
Show cracks appearing in aging projects
Display throughput vs decay stats
Slow worker side:
Draw worker with focused beam to current work
Draw completed projects as solid, glowing blocks
Show progress ring on current project
Display completion and longevity stats
Show final message about velocity vs value
Source Code
let sketch = function(p) {
let fastWorker;
let slowWorker;
let time = 0;
class FastWorker {
constructor() {
this.x = 100;
this.y = 150;
this.projects = [];
this.completedCount = 0;
this.decayedCount = 0;
}
update() {
// Rapidly create new projects
if (p.frameCount % 20 === 0) {
this.projects.push({
x: this.x,
y: this.y - 40,
age: 0,
completed: false,
decayed: false,
alpha: 255
});
this.completedCount++;
}
// Update projects
for (let i = this.projects.length - 1; i >= 0; i--) {
let proj = this.projects[i];
proj.age++;
// Projects quickly decay (poor quality from velocity)
if (proj.age > 100 && !proj.decayed) {
proj.decayed = true;
this.decayedCount++;
}
// Fade out decayed projects
if (proj.decayed) {
proj.alpha = p.max(0, proj.alpha - 5);
if (proj.alpha <= 0) {
this.projects.splice(i, 1);
}
} else {
// Move upward before decay
proj.y -= 0.4;
}
}
}
display(colors) {
// Draw worker
p.noStroke();
p.fill(...colors.accent3, 200);
p.circle(this.x, this.y, 14);
// Motion blur effect (rapid movement)
for (let i = 1; i <= 3; i++) {
p.fill(...colors.accent3, 60 / i);
p.circle(this.x + i * 4, this.y, 14);
}
// Draw projects
for (let proj of this.projects) {
if (proj.decayed) {
// Decayed projects - crumbling apart
p.fill(...colors.accent3, proj.alpha * 0.4);
} else {
// Active projects - but fragile looking
p.fill(...colors.accent3, proj.alpha * 0.7);
}
// Small, quickly produced blocks
p.rect(proj.x - 4, proj.y - 4, 8, 8);
// Cracks appear as they age
if (proj.age > 50 && !proj.decayed) {
p.stroke(...colors.bg, 150);
p.strokeWeight(1);
p.line(proj.x - 4, proj.y, proj.x + 4, proj.y);
}
}
}
}
class SlowWorker {
constructor() {
this.x = 300;
this.y = 150;
this.currentProject = null;
this.completedProjects = [];
this.progress = 0;
this.completedCount = 0;
}
update() {
// Working on one project at a time
if (!this.currentProject) {
this.currentProject = {
x: this.x,
y: this.y - 40,
progress: 0
};
this.progress = 0;
}
// Slow, steady progress
this.progress += 0.5;
this.currentProject.progress = this.progress;
// Complete project after sustained work
if (this.progress >= 100) {
this.completedProjects.push({
x: this.currentProject.x,
y: this.currentProject.y,
age: 0,
alpha: 255
});
this.currentProject = null;
this.progress = 0;
this.completedCount++;
}
// Update completed projects - they last much longer
for (let proj of this.completedProjects) {
proj.age++;
proj.y -= 0.15; // Slow rise (enduring value)
}
}
display(colors) {
// Draw worker (calm, focused)
p.noStroke();
p.fill(...colors.accent2, 200);
p.circle(this.x, this.y, 14);
// Focused beam toward current work
if (this.currentProject) {
p.stroke(...colors.accent2, 40);
p.strokeWeight(15);
p.line(this.x, this.y, this.currentProject.x, this.currentProject.y);
}
// Draw completed projects - solid, lasting
for (let proj of this.completedProjects) {
// Solid, well-crafted blocks
p.noStroke();
p.fill(...colors.accent2, proj.alpha);
p.rect(proj.x - 10, proj.y - 10, 20, 20);
// Glow indicating quality
p.fill(...colors.accent2, proj.alpha * 0.3);
p.rect(proj.x - 13, proj.y - 13, 26, 26);
}
// Draw current project with progress
if (this.currentProject) {
// Foundation being built
let height = p.map(this.progress, 0, 100, 2, 20);
p.noStroke();
p.fill(...colors.accent2, 180);
p.rect(this.currentProject.x - 10, this.currentProject.y - height/2, 20, height);
// Progress ring
let progressAngle = p.map(this.progress, 0, 100, 0, p.TWO_PI);
p.noFill();
p.stroke(...colors.accent2, 200);
p.strokeWeight(2);
p.arc(this.currentProject.x, this.currentProject.y, 30, 30, -p.HALF_PI, -p.HALF_PI + progressAngle);
}
}
}
p.setup = function() {
p.createCanvas(400, 300);
p.colorMode(p.RGB);
p.rectMode(p.CENTER);
fastWorker = new FastWorker();
slowWorker = new SlowWorker();
};
p.draw = function() {
const colors = getThemeColors();
p.background(...colors.bg);
time++;
// Labels
p.noStroke();
p.fill(...colors.accent1, 180);
p.textAlign(p.CENTER);
p.textSize(11);
p.text('High Velocity', 100, 30);
p.text('Considered Pace', 300, 30);
// Divider
p.stroke(...colors.accent1, 50);
p.strokeWeight(1);
p.line(200, 40, 200, 260);
// Update and display
fastWorker.update();
slowWorker.update();
fastWorker.display(colors);
slowWorker.display(colors);
// Stats
p.noStroke();
p.textSize(9);
p.textAlign(p.LEFT);
p.fill(...colors.accent3, 150);
p.text(`Shipped: ${fastWorker.completedCount}`, 20, 270);
p.text(`Decayed: ${fastWorker.decayedCount}`, 20, 283);
p.textAlign(p.RIGHT);
p.fill(...colors.accent2, 150);
p.text(`Shipped: ${slowWorker.completedCount}`, 380, 270);
p.text(`Lasting: ${slowWorker.completedProjects.length}`, 380, 283);
// Bottom message
p.textAlign(p.CENTER);
p.fill(...colors.accent1, 140);
p.textSize(9);
p.text('Velocity measures speed, not value', 200, 295);
};
};