Running a Remote Engineering Team Across Time Zones
Managing a remote engineering team sounds straightforward until you have developers in Lahore, designers in Lisbon, and a client in Los Angeles. That is a 13-hour spread. When your backend engineer in Pakistan starts their day, your frontend developer in Portugal is having lunch, and your client in California is asleep. Coordination does not happen by accident in this setup. It happens because you build systems that make it inevitable.
Harbor Software has operated as a distributed team since 2019. We did not choose remote work because of a pandemic. We chose it because the best WordPress engineers we could find were not all in the same city, and pretending otherwise would have meant hiring mediocre talent close by instead of excellent talent far away. Five years in, we have refined our approach through painful trial and error. Here is what actually works, what we abandoned, and what we wish someone had told us on day one.
The Overlap Window Is Everything
The single most important concept in distributed team management is the overlap window: the hours where two or more team members are simultaneously online and available for synchronous communication. Every other practice we have adopted flows from protecting and maximizing these windows.
For a team spanning UTC+5 (Pakistan) to UTC-8 (US West Coast), the natural overlap is almost zero. If your Pakistani engineer works 9 AM to 6 PM PKT, that is 11 PM to 8 AM Pacific. Your California client is asleep for the entire Pakistani workday. This is not a scheduling problem you can hack around with clever tooling. It is a physics problem.
Our solution is structured shifts with deliberate overlap. Senior engineers in Pakistan shift their schedules to 11 AM – 8 PM PKT, creating a 2-hour overlap with European teammates (who work 9 AM – 6 PM WEST) and a 1-hour overlap with US West Coast clients (who typically start at 9 AM Pacific, which is 8 PM PKT). That single shifted hour is enough for a daily standup and one decision-making conversation.
The cost of this shift is real. You are asking people to work non-standard hours. We compensate for this with flexible scheduling on Fridays, where engineers can revert to their natural timezone schedule, and with explicit acknowledgment that shifted schedules are a sacrifice, not an expectation. Engineers who consistently take the shifted schedule receive a 10% timezone premium on their base rate, which we budget as part of the project cost, not as an afterthought.
We also discovered that overlap quality matters more than overlap quantity. Two hours of focused, agenda-driven overlap beats four hours of Slack-open-in-the-background half-attention. During overlap windows, we have a strict no-heads-down-coding rule: you are available for questions, reviews, and decisions. Deep work happens outside the overlap. This distinction between overlap time and deep-work time is the most important scheduling concept we have implemented.
Asynchronous Communication as a First-Class Practice
Most remote work advice tells you to “communicate asynchronously.” That is about as useful as telling someone to “eat healthy.” The detail matters. Here is how we actually practice async communication at Harbor:
The Daily Handoff Document
Every engineer writes a handoff at the end of their workday. This is not a status update. It is a briefing for the person who will work on the project next. The format is rigid and non-negotiable:
## Handoff - [Name] - [Date]
### What I completed today
- Implemented product filter API endpoint (PR #234)
- Fixed pagination bug on category pages (PR #235)
### What is blocked
- Waiting on client approval for checkout flow mockup
- Need database credentials for staging environment
### What the next person should pick up
- PR #234 needs review - look specifically at the query
optimization on line 45, I am not sure the index covers it
- The WooCommerce webhook for order status is firing twice;
I narrowed it to the save_post hook but ran out of time
### Decisions needed
- Should we paginate the product API at 20 or 50 items?
Client has not specified. I defaulted to 20.
### Context that would take 30 minutes to figure out
- The staging site SSL cert expired yesterday. I renewed it
but the CDN cache still has the old cert. Purge Cloudflare
if you see HTTPS errors.
That last section is the most valuable. It captures tribal knowledge that would otherwise be lost between shifts. Without it, the next engineer spends 30 minutes debugging an SSL error that has already been diagnosed. Multiply that by five engineers across three timezones and you lose hours every day to re-discovery of information that someone already found.
We store handoffs in a dedicated Slack channel, not in project management tools. The reason is searchability and speed. When an engineer starts their day, they check the handoff channel first. It takes two minutes to read and they know exactly where to start. Burying this information in Jira tickets or Notion pages adds friction that kills adoption. We tried Notion first, and handoff completion dropped from 90% to 40% within two weeks because the extra clicks to navigate to the right page were enough to make people skip it.
Loom Over Meetings
We record approximately 15 Loom videos per week as a team. Code walkthroughs, bug demonstrations, design feedback, architecture explanations. A 5-minute Loom replaces a 30-minute meeting because the viewer can watch at 2x speed, pause to examine code, and rewatch sections they missed. The recording is available to everyone regardless of timezone, which means no one is excluded from the conversation because they were asleep when the discussion happened.
We have a naming convention for Looms that makes them searchable: [Project] [Type] [Topic] - [Date]. For example: Autostore CodeWalk Cart API Refactor - 2024-01-15. Types are CodeWalk, BugDemo, DesignReview, ArchDecision, or ClientUpdate. This convention means six months later, when someone needs to understand why the cart API was refactored, they can find the original explanation in seconds rather than asking around or reverse-engineering the git history.
Code Review Across Time Zones
Code review is where timezone distribution hurts the most. In a co-located team, you tap someone on the shoulder, they review your PR in an hour, and you merge before lunch. In a distributed team, your PR sits for 8-12 hours waiting for a reviewer in a different timezone to start their day. That delay compounds across multiple PRs in a sprint, and before you know it, your team is spending more time waiting for reviews than writing code.
We have reduced our average PR review time from 14 hours to 4 hours with three changes:
First, small PRs are mandatory. Our hard limit is 400 lines of changed code. Beyond that, the PR must be split. Large PRs do not just take longer to review; they sit longer because reviewers procrastinate on them. A 100-line PR gets reviewed in 15 minutes. A 1,200-line PR gets postponed until tomorrow, which in timezone terms means the day after tomorrow for the author. We enforced this limit with a GitHub Action that adds a “needs-split” label to any PR over 400 lines, preventing merge until it is addressed.
Second, we have a review SLA. Every PR must receive its first review within 4 business hours of submission. Business hours are calculated based on the reviewer’s timezone. If a PR is submitted at 5 PM PKT and the reviewer is in UTC+1, the SLA starts at 9 AM the next day in their timezone. We track this metric weekly and display it on a dashboard visible to the entire team. Engineers who consistently miss the SLA have a conversation with their lead about priorities and workload.
Third, self-review comments. Before requesting review, the author adds inline comments on their own PR explaining non-obvious decisions. This is different from code comments (which explain the code to future maintainers). Self-review comments explain the code to the reviewer right now:
// Self-review comment on a PR:
// I chose to denormalize the category data here instead of
// joining at query time. The category table has 10 rows and
// changes once a month. The product table has 50,000 rows
// and this query runs on every page load. The denormalization
// saves ~40ms per request based on EXPLAIN ANALYZE.
These comments cut review back-and-forth in half. Without them, the reviewer asks “why did you denormalize this?” and waits 8 hours for the answer. With them, the reviewer understands the reasoning immediately and can focus on whether the reasoning is sound rather than guessing at intent.
Tooling That Bridges Time Gaps
Our tool stack is deliberately minimal. Every tool must justify its existence by solving a specific timezone problem. Here is what we use and why:
- Slack – Primary async communication. We use threads religiously. A message without a thread is a message that will be lost in the scroll. We have a bot that flags unthreaded messages in project channels and reminds people to reply in threads.
- Linear – Issue tracking. We switched from Jira in 2022. The speed difference is not trivial; when you check your task board 10 times a day, a tool that loads in 500ms versus 3 seconds saves real cognitive energy. Linear’s API is also cleaner for our automation scripts that generate status reports.
- GitHub – Code hosting and review. We use GitHub Actions for CI/CD, branch protection rules for review requirements, and CODEOWNERS files to auto-assign reviewers based on which files are changed.
- Loom – Async video. Already covered above. The investment in Loom paid for itself within the first month of use.
- Tuple – Pair programming during overlap windows. When two engineers are online simultaneously and working on a complex problem, Tuple’s low-latency screen sharing is worth its subscription cost in the first session.
- World Time Buddy – Sounds trivial, but having a persistent multi-timezone clock visible at all times prevents scheduling mistakes. We embed it in our Slack sidebar so everyone can see at a glance who is online.
Tools we tried and dropped: Notion (too slow for daily use, became a graveyard of unread documents), Miro (useful for workshops but not daily work), Microsoft Teams (the threading model is hostile to async communication and drives people toward synchronous calls), and Basecamp (great philosophy about calm work, but inadequate for the level of technical project management we need).
Decision-Making Without Synchronous Consensus
The hardest part of distributed work is not coordination; it is decision-making. In a co-located team, you gather in a room, debate for 30 minutes, and walk out with a decision. In a distributed team, that debate stretches across 48 hours of async back-and-forth, and by the time everyone has weighed in, the context has shifted and someone has already started implementing the option that seemed most likely to win.
We use a modified RFC (Request for Comments) process for decisions that affect more than one person’s work. The process has four phases with hard time limits:
- Proposal (24 hours) – One person writes a proposal in a structured format: Context, Problem, Proposed Solution, Alternatives Considered, Trade-offs, and Questions. This is posted in the relevant project channel with an @channel mention.
- Comment (48 hours) – Team members add comments, concerns, and alternative suggestions. The proposal author responds to each point. We use emoji reactions to signal agreement (thumbs up), concern (thinking face), or blocking objection (stop sign) without writing a full response.
- Decision (24 hours) – The designated decision-maker (usually the tech lead for technical decisions, the project manager for process decisions) makes the call. The decision is posted as a reply with the reasoning and any modifications based on feedback.
- Record (immediate) – The decision is logged in our architecture decisions record (ADR) with a link to the discussion thread. This is a markdown file in the project repository that becomes a permanent record of why we chose what we chose.
The time limits are critical. Without them, decisions drift for weeks while people wait for one more person to weigh in. A 96-hour maximum from proposal to decision means no architectural question blocks progress for more than four days. In practice, most decisions close in 48 hours because the structured format forces clarity upfront and reduces the need for clarification rounds.
For urgent decisions that cannot wait for the full RFC cycle, the person who encounters the decision has authority to make it, document it, and move forward. They post the decision with a [URGENT DECISION] tag and the reasoning. The team can challenge it within 24 hours, but the default is that the decision stands. This prevents timezone gaps from creating decision paralysis, which is the most insidious failure mode of distributed teams.
Hiring for Remote and Timezone Resilience
Not every engineer thrives in a distributed team. We have learned to screen for timezone resilience during hiring, and we have identified the traits that predict success versus the traits that predict frustration and eventual departure:
- Written communication skill – If a candidate cannot explain a technical concept clearly in writing during the interview process, they will struggle in a team where 80% of communication is text-based. We include a written technical exercise in every interview: explain a past architectural decision in 500 words or fewer. The quality of this write-up is weighted as heavily as the technical assessment.
- Self-direction – Distributed engineers often work 4-6 hours without any synchronous contact. They need to identify the next task, unblock themselves when possible, and escalate appropriately when not. We probe for this with situational questions: “You are stuck on a bug and your tech lead is offline for the next 6 hours. Walk me through your next steps.” Candidates who say “wait for the tech lead” are not a fit.
- Documentation habit – Engineers who naturally document their work (commit messages, PR descriptions, code comments) produce less friction in distributed teams. We look at their GitHub profiles and past PR descriptions during evaluation. An engineer with well-written commit messages is signaling that they think about the reader, not just the code.
- Timezone awareness – Have they worked across timezones before? Do they understand that scheduling a “quick call” at 9 AM their time might be 11 PM for a colleague? This awareness is hard to teach and easy to screen for in the interview process by asking about their experience with distributed teams.
We explicitly do not screen for “always available” mentality. Engineers who respond to Slack messages at midnight are not dedicated; they are heading toward burnout that will cost the team more in the long run than any after-hours message could save. We want people who are intensely focused during their working hours and completely offline afterward. Sustainable pace is not a perk; it is an operational requirement for a team that depends on every member showing up sharp every day.
Measuring What Matters
We track five metrics that tell us whether our distributed team is functioning well:
- PR review latency – Median time from PR submission to first review. Target: under 4 hours. Current: 3.2 hours.
- Handoff completion rate – Percentage of workdays with a completed handoff document. Target: 95%. Current: 91%.
- Decision cycle time – Median time from RFC proposal to recorded decision. Target: under 72 hours. Current: 52 hours.
- Blocked time – Hours per week where an engineer is blocked waiting for a response from someone in another timezone. Target: under 3 hours/week. Current: 2.4 hours.
- After-hours messages – Slack messages sent outside an engineer’s declared working hours. Target: as low as possible. A rising trend signals overwork or timezone pressure that needs to be addressed immediately.
We do not track lines of code, commit counts, or hours logged. These metrics incentivize the wrong behavior in a distributed team. An engineer who writes 200 lines of well-documented code with a clear PR description and a thorough handoff is more valuable than one who pushes 800 lines with no context, because the first engineer’s work can be understood and continued by anyone on the team.
The blocked-time metric is the most actionable. When it spikes for a specific engineer, we investigate. Usually the cause is a dependency on a single person in a different timezone who holds specialized knowledge. The fix is either cross-training (so someone in the same timezone can answer the question) or documentation (so the answer exists in a searchable location that does not require any human to be online). Every spike is a signal that our async practices have a gap that needs to be filled.
The Reality Check
Distributed teams are not universally better or worse than co-located teams. They are different, with different strengths and different failure modes. The strengths are real: access to global talent, lower overhead costs, built-in documentation culture, and the ability to have work happening across 16 hours of the day instead of 8.
The failure modes are also real: loneliness, communication gaps, decision delays, and the ever-present temptation to “just hop on a quick call” that excludes half the team. The teams that succeed at distributed work are the ones that acknowledge these failure modes and build systems to mitigate them, rather than pretending that remote work is all upside.
If you are building a remote engineering team, start with the overlap window. Figure out where your team’s timezones create natural overlaps and protect those hours ruthlessly. Build your async practices around the gaps. Hire people who write well and work independently. Measure the things that matter. And accept that some things will always be harder than they would be in an office. The question is not whether distributed work has costs. It does. The question is whether the benefits, primarily access to talent, outweigh those costs. For Harbor Software, five years in, the answer remains yes.