The 15-Second Debounce - Smart Build Triggering

The 15-Second Debounce: Smart Build Triggering

There's something deeply satisfying about hitting publish and watching your changes go live instantly. But behind that smooth experience is a small piece of engineering that's saved us from burning money on unnecessary compute.

Let me tell you the story of our 15-second debounce.

The Problem We Didn't Know We Had

When I first built Jottings, every edit triggered an immediate rebuild. You'd edit a jot, click save, and within seconds your static site regenerated with your changes. It felt responsive. It felt good.

Then I started thinking about what actually happens during that rebuild:

  1. Lambda spins up (cold start or warm)
  2. We fetch all your jots from DynamoDB
  3. We parse markdown for each one
  4. We generate HTML pages
  5. We minify CSS and HTML
  6. We upload everything to Cloudflare R2

That's a lot of work for a 150-character update.

Now imagine you're rapidly drafting something—editing a sentence, fixing a typo, rewording a paragraph. Five edits in 30 seconds. Under the original system, that's five full rebuilds. Five Lambda invocations. Five R2 uploads. All burning through compute minutes and storage requests while you're still typing.

The math was depressing. For a user who makes 5 rapid edits before leaving their dashboard, we'd spend 4 of those rebuilds on work that immediately became obsolete.

Enter the Debounce

The solution was beautifully simple: wait 15 seconds before triggering a build.

Here's how it works:

First edit: User saves a jot. Instead of immediately queuing a build, we set a timer. We wait.

More edits within 15 seconds: Another save comes in. We cancel the previous timer and restart it for another 15 seconds. We're essentially saying, "I'll wait 15 more seconds to see if they're done editing."

No edits after 15 seconds: Timer expires. Now we queue the build. One rebuild for however many edits happened in that window.

It's a pattern called "debouncing" in frontend development, but we apply it server-side at the build trigger layer. AWS SQS and DynamoDB make this straightforward—we maintain a lastBuildTriggeredAt timestamp and check elapsed time before actually queuing work.

The Numbers

Let's get concrete about the impact.

For an average user making 10 edits per session:

  • Without debouncing: 10 Lambda invocations, 10 R2 uploads, ~30 seconds of compute
  • With 15-second debounce: 1 Lambda invocation, 1 R2 upload, ~3 seconds of compute

That's a 90% reduction in compute for typical editing sessions. Over hundreds of users, it's significant.

The 15-second window isn't magic. It's calibrated to feel responsive—if you stop editing for more than 15 seconds, you're probably done. But it's long enough to catch rapid-fire edits without making users feel like the platform is sluggish.

We actually considered 10 seconds (snappier) and 30 seconds (more aggressive). Fifteen felt like the sweet spot between responsiveness and efficiency.

Why This Matters

It's easy to dismiss optimization like this as premature. "Just rebuild everything," you might think. "Compute is cheap."

But here's what I've learned: compute is cheap individually, but it compounds. Every unnecessary Lambda invocation adds latency. Every extra R2 request adds to our bill. Every rebuild that happens while you're still thinking about your next edit is wasted energy.

More importantly, it's about respecting what serverless infrastructure actually is. AWS Lambda bills you by the millisecond. Our platform should use exactly what it needs, no more.

There's also an environmental angle. Every unnecessary compute cycle is electricity. It's not nothing.

The Subtle UX Win

Here's something I didn't anticipate: debouncing actually improves the user experience in a way that's hard to quantify.

Without debouncing, every save triggers an immediate rebuild. If a user is editing on a slower connection, they might see their site flickering as it rebuilds. Save jot → rebuild → done. Edit → save → rebuild. It's noisy.

With debouncing, edits feel grouped. You make several changes, and when they're done, the site updates once. It feels more stable. Less chaotic.

How We Implemented It

For the curious, the implementation lives in our build trigger logic. When a jot is created or updated, instead of immediately publishing to SQS, we:

  1. Check if a build was triggered in the last 15 seconds
  2. If yes, skip queuing (the existing timer will catch these changes)
  3. If no, queue the build and update the timestamp

It's handled in the API layer, just a few lines of logic around our SQS publisher:

const timeSinceLastBuild = Date.now() - (site.lastBuildTriggeredAt || 0);
if (timeSinceLastBuild < 15000) {
  // Still within debounce window, skip build trigger
  return;
}

// Time to build
await triggerBuild(siteId);

Not One-Size-Fits-All

I should note: debouncing isn't universally the right answer. If you're building a collaborative editor with multiple users, instant rebuilds might be important. If you're deploying critical infrastructure, you want changes applied ASAP.

But for a personal microblogging platform where individual users are editing their own content? Debouncing is perfect. It optimizes for the common case: thinking before publishing.

The Bigger Picture

This is one of those technical decisions that barely anyone will notice. Users will just think, "It feels fast and responsive." They won't know we're being smart about when we rebuild their site behind the scenes.

And honestly, that's the goal. Good infrastructure should be invisible.

If you're building something on Jottings right now and you notice your site updates smoothly even when you're rapid-firing edits, that's the 15-second debounce working. It's letting you think, edit, iterate—and only rebuilding when you're actually done.

It's small, but it's how we keep things simple, efficient, and affordable.


If you're interested in how Jottings handles other efficiency optimizations—from client-side image resizing to atomic database transactions—I'd love to have you explore the platform. Sign up for free and start building your microblog today.