I've worked async for the last six years — fully remote, four time zones away from most colleagues. Done well, async work is calmer, lets you focus longer, and produces better artifacts than meeting-driven workflows. Done poorly, it's a slow grinding hell of waiting for replies.
Here's what I've learned about doing it well.
The Core Principle
Async work optimizes for decision throughput per day, not for bytes communicated per minute. Every interaction has fixed overhead (writing it down, the recipient context-switching to read it). The optimization is to batch enough information into each interaction that recipients can act without follow-ups.
A 10-line message that gets a clear "approved" the next day beats five back-and-forth Slack threads stretched over a week.
Write Like You Won't Be There
The single skill that defines async-fluent engineers: writing self-contained messages.
Bad:
Hey, can you check out the auth thing?
Good:
The login flow on /auth.alaminahamed.com is failing for users with passkeys
on Firefox 124 (Mac). Repro in 30 seconds:
1. Visit /auth/login
2. Click "Sign in with passkey"
3. Browser shows passkey picker, but on selection, the page errors with
"RP ID mismatch"
Logs: https://logs.example.com/L?q=passkey&since=24h
Hypothesis: the RP ID check uses request->host which now resolves to
auth.alaminahamed.com instead of alaminahamed.com after the subdomain split.
If that's right, fix is in PasskeyController::challenge — switch to using
config('auth.passkeys.rp_id') instead.
Could you take a look or hand it back to me with what you see?
The good message includes: what's wrong, how to reproduce, where the data is, the author's hypothesis, and the proposed fix. The recipient can act on it without asking anything.
This costs you 5 minutes more to write. It saves the recipient a 30-minute clarification cycle. Net positive.
Status Updates Have a Specific Shape
Async standups should answer three things:
- What I shipped since the last update
- What I'm working on now (one specific thing)
- What's blocked or unclear
In that order. Anything else is filler.
Yesterday: Shipped passkey support behind a feature flag (PR #142). Wrote
tests covering registration and login. Caught a Firefox issue
with RP ID resolution, fix went out as a follow-up.
Today: Wiring up the admin profile page UI for managing passkeys.
Should land by EOD.
Blocked: Need design review on the "remove passkey" confirmation dialog.
@design-team — can someone take a quick look at #150?
Two minutes to write, two minutes for the team to read. Replaces a 15-minute call.
When To Pick Up The Phone
Async is the default, not the rule. Switch to synchronous (call/video) when:
- You've gone three round-trips without convergence
- The topic is sensitive (interpersonal feedback, performance, conflict)
- You're brainstorming and the bandwidth of typing is the bottleneck
- Time-critical decisions with hard deadlines
Then write up the outcome async so people who weren't there can catch up.
Time-Zone Etiquette
If you're 8 hours offset from your team:
- Don't use
@hereor@channeloutside business hours unless it's a real emergency - Send messages with the receiver's timezone in mind ("by tomorrow EOD" is ambiguous)
- Set a Slack notification schedule — the team should never see you online at 3am
- Build a buffer of work that doesn't depend on real-time input
Documentation As Async Communication
The best async signal is a wiki/doc that answers a question before someone asks. When you find yourself writing the same explanation twice, write it once in a permanent place and link to it instead.
The compounding effect is real — after a year, ~70% of "how do we...?" questions get answered with "see the doc on X". The team's bandwidth goes up.
I keep a personal decisions/ folder. Every architectural decision gets a one-page doc with: the decision, alternatives considered, the trade-offs, and the date. Six months later when someone asks "why didn't we do X?", the doc answers without me needing to remember.
The Trap I Fell Into
For the first two years, I over-rotated on async. I would draft a 500-word message instead of a 10-minute call, "to respect everyone's focus time". The result: decisions took weeks, my colleagues felt I was avoiding them, and the team velocity dropped.
The fix wasn't fewer async messages. It was learning to recognize the failure modes — when async was costing more than it saved — and switching modes confidently.
Async is a tool, not an ideology. Use it when it fits.
Al Amin Ahamed
Senior software engineer & AI practitioner. Laravel, PHP, WordPress plugins, WooCommerce extensions.
About me →More from the blog
← Older
The Honest Economics of Selling WordPress Plugins
Newer →
Laravel Queues at Scale: Lessons from 10 Million Jobs
One email a month. No noise.
What I shipped, what I read, occasional deep dive. Unsubscribe anytime.
Check your inbox — confirmation link sent.