Time-off request system design for clear policies and approvals
Time-off request system design made simple: define policies, handle accrual math, route manager approvals, and keep calendars accurate without messy workflows.

What breaks in most time-off processes
People expect a time-off request to feel like booking a meeting: pick dates, see your balance, get a clear yes or no, and have it show up everywhere it needs to. When it does not work that way, teams fall back to “just message me,” and the system becomes a record-keeping chore instead of a reliable tool.
Requests usually get stuck in the handoffs: an email thread that misses the right manager, a spreadsheet that no one updates, or a chat approval that is impossible to audit later. The employee thinks they are covered, the manager thinks HR will handle it, and HR finds out at payroll time that the balance is wrong.
The real goal of time-off request system design is boring but important: correct balances, clear approvals, and one source of truth. If your balance is right but approvals are unclear, managers will keep asking “Did I already approve this?” If approvals are perfect but the calendar is wrong, teams still double-book.
Four groups rely on the same workflow, but for different reasons:
- Employees: fast requests, instant status, and confidence it is recorded
- Managers: the right request routed to them, with enough context to decide
- HR/payroll: policies applied consistently and balances that match pay rules
- The business: team visibility without exposing private details
A “readable workflow” means you can look at the steps and explain them in plain language: what triggers the request, who approves, what happens on rejection, and what is written back (balance, status, calendar). If you cannot explain it quickly, people will bypass it.
Tools like AppMaster can help by keeping the logic visual and centralized, so policy changes do not turn into a maze of emails and exceptions.
The basic data you need (without overbuilding it)
A good time-off tool is mostly a clean set of records and a few clear relationships. If you get the basics right, the rest of your time-off request system design stays readable, even when policies and approvals grow later.
Start with a small set of core objects that you can explain in one minute:
- Employee: who is requesting time off (and who approves them).
- TimeOffRequest: the actual request (dates, type, status).
- Policy: the rules for a leave type (PTO, sick, unpaid).
- Balance: the current available amount for an employee and policy.
- Approval: decisions and comments tied to a request.
For requests, the fields that prevent real-world pain are not fancy. They are specific. Store start and end date/time, whether it is a partial day, and the employee’s timezone at the time of the request. Add a short reason, and allow attachments if your HR process needs proof (for example, a doctor note). Keep attachments optional so you do not block normal PTO.
Statuses should be few and predictable: draft (saved but not sent), submitted, approved, rejected, and canceled. Avoid extra statuses like “pending HR” unless you truly need them.
Do not skip the audit trail. Even a minimal “who changed what and when” saves you in disputes. At minimum, log submit, approve, reject, cancel, and any date edits.
For teams, locations, and departments, treat them as separate reference data. Link employees to these groups, and link policies to the groups they apply to. That way, when someone moves offices, you update one employee record, not every policy.
If you build this in AppMaster, keep each object simple first, then add validations and workflow steps once the data is stable.
Policy rules: keep them clear and testable
Good policies are boring on purpose. People should be able to predict the outcome before they click Submit. In time-off request system design, the fastest way to lose trust is when the same request gets approved one week and rejected the next.
Start by naming your leave types and writing one plain sentence for each. Vacation or PTO is planned time away. Sick leave is unplanned health-related time. Unpaid leave is time off with no pay. Parental leave often has special dates and documents. Comp time is earned by extra hours and spent like PTO.
Eligibility rules should read like a checklist, not a legal doc. Keep them explicit: who can use it (full-time, part-time, contractors), when it starts (after probation, after X days), and whether it depends on tenure. If a rule has exceptions, write the exception as its own rule, not a footnote.
Request rules are where confusion usually starts. Be specific about notice periods, blackout dates, and the smallest allowed chunk of time. For example: “Vacation requests must be submitted 5 business days in advance, except emergencies approved by HR” is testable. “Submit early” is not.
Carryover and expiration rules should fit in one sentence. Example: “Up to 40 hours carry over to next year and expire on March 31.” If you need a second sentence, that is a hint the policy is doing too much.
Here is a simple way to keep policy text and rule logic in sync:
- Give every rule a short ID (like PTO-NOTICE-5D)
- Store the plain-language text next to the rule configuration
- Add 2 to 3 sample cases per rule (approved or rejected) as tests
- Change policy text only when the rule configuration changes (and vice versa)
Example: An employee in probation requests 2 hours of PTO for tomorrow. The system should block it for two reasons that are easy to read: “PTO starts after 60 days” and “PTO needs 5 business days notice.” If you build in AppMaster, keep those messages close to the rule nodes so updates do not drift over time.
Accrual math: the patterns that cause confusion
Accrual is where a time-off request system design often gets messy, because small rules add up. The goal is not fancy math. The goal is predictable results that match what HR and employees expect when they check a balance.
One common confusion is mixing accrual styles. Some companies add hours every pay period, others add monthly, some accrue per hour worked, and some grant the full annual amount on a fixed date. Problems start when you store only “balance” and forget “how it was earned.” Keep a clear record of events: grant, accrue, adjustment, and usage.
Proration is another trap. A new hire who starts mid-month, or an employee who changes from part-time to full-time, should not need a manual spreadsheet fix. Decide one rule and stick to it. For example: prorate by calendar days in the period, or by scheduled hours. Whichever you choose, write it down in plain words and encode it the same way everywhere.
Caps and negative balances cause “it looks wrong” tickets. If you allow carryover up to a cap, apply the cap at a specific moment (end of year, end of accrual period, or after each accrual). If negative balances are allowed, define the limit and what happens on termination.
Rounding rules create silent drift. Pick one rounding level (minutes, quarter-hours, or half-days) and apply it consistently to both accrual and usage. If you accrue in minutes but request in half-days, employees will always feel the system is off.
Backdated requests and corrections need an audit trail. If someone submits a request for last week, the system should recalculate from the request date forward and log the change.
A simple checklist that prevents most disputes:
- Store balance changes as dated transactions, not just a single number
- Recalculate from an effective date when policy inputs change
- Apply caps and rounding in one shared function
- Keep manual adjustments separate from accrual logic
- Always show “as of date” for any displayed balance
In AppMaster, this usually maps cleanly to a Transactions table plus a small business process that recomputes balances when a request is approved or corrected.
Manager approvals: simple routing that still covers edge cases
A manager approval workflow should answer one question: who can say “yes” with confidence? If you try to model every org chart detail, your time-off request system design becomes hard to read and even harder to fix.
Start with one default rule: the employee’s direct manager approves. Then add only the exceptions that change risk or accountability. Keep the rule order explicit, so you can explain outcomes without digging through settings.
One-step vs multi-step approvals
Most teams can use a single approval step for standard PTO. Add steps only when the request affects payroll, compliance, or coverage across teams.
Common patterns that stay readable:
- One-step: Manager approves for standard PTO and unpaid leave.
- Two-step: Manager then HR for leave types that require documents or policy checks.
- Second approver: Add a department head only when the absence impacts shared coverage (for example, on-call rotations).
- Auto-approve: Low-risk requests, like 1-2 hours for an appointment, or time that’s already pre-approved in a schedule.
- No manager: HR-only approval for contractors or roles without a clear manager.
Delegation, rejections, and resubmits
Approvals break when the approver is out. Make delegation a first-class rule, not a manual workaround. If the manager is marked out-of-office, route to a delegate; if there is no delegate, route to the manager’s manager (or HR as a fallback). Always log which rule picked the approver.
Rejections and edits are where systems get messy. Keep it simple: a rejection closes the request with a required reason. If the employee edits dates or leave type, treat it as a resubmission and re-run routing from scratch. That prevents “half-approved” requests that no longer match what was approved.
A practical example: Alex requests 3 days of sick leave. The system routes it to the manager, but because it’s a policy-controlled leave type, HR gets a second step only after manager approval. If the manager is out, the delegate approves, and the audit trail shows why.
If you build this in AppMaster, keep routing logic in one visual process with a small set of rules in a clear order, so anyone can read and maintain it later.
Validation rules before you let a request through
Good validation keeps the time-off request system design readable because it prevents special cases from leaking into approvals. Aim for rules that are easy to explain and easy to test.
Start with booking rules. Overlap checks should catch conflicts with existing approved leave and pending requests. Be explicit about partial days: store the date plus a simple unit like AM, PM, or hours so half-days do not get rounded into full days by accident. Also decide what to do with weekends and company holidays: either block them or allow them but ignore them in the day count.
Balance checks are trickier than they look. Many teams validate balance at submit time (so people do not spam requests) and re-check at approval time (because accruals and other approvals may change the balance). If you do both, show the user which point failed.
Here is a clean set of validations that covers most cases:
- Dates are valid (start before end, same timezone, no missing half-day choice)
- No overlap with existing leave (including half-days)
- Day count excludes weekends and holidays (based on your policy)
- Required attachments are present for specific leave types (for example, sick leave note)
- Balance is sufficient (check at submit, and again at approve)
Team coverage checks can help, but avoid hard blocks unless you must. A better default is a warning that lets a manager decide. Example: “Two people on your team are already out that day. Submit anyway?”
Make error messages fair and fixable. Tell users what failed, where, and how to correct it. For example: “Your request overlaps with an approved PTO on Mar 12 (PM). Choose a different time or edit the existing request.”
If you build this in AppMaster, keep validations close to the request form and reuse the same checks in the approval step, so rules do not drift over time.
Step-by-step: a readable workflow you can build and maintain
A good time-off request system design feels boring in the best way: every request follows the same path, and every decision has one clear reason. The easiest way to keep it readable is to separate policy data (what the rules are) from workflow logic (what happens when someone clicks Submit).
Here’s a sequence that stays simple even as you add more leave types later:
- Put every leave type and rule in one place (names, eligibility, carryover, blackout periods). If a rule is not written down here, it should not exist anywhere else.
- Model balances as a timeline, not a single number. Store opening balance, earned (accrual), used, and adjustments so you can explain any balance on any date.
- Build the request form with early checks. Validate dates, partial days, overlaps, notice periods, and “enough balance by the start date” before approvals begin.
- Route approvals using a small set of roles (employee, direct manager, HR). Add exceptions as data (like “needs HR review if 10+ days”) instead of hardcoding special cases.
- Create calendar events only after approval, and treat them as synced records that can be updated or canceled when the request changes.
Keep the workflow readable by logging each decision in plain language (for example: “Rejected: overlaps existing approved leave”). If you use a visual workflow tool like AppMaster’s Business Process Editor, label steps the way a human would read them.
Before launch, test with real scenarios: backdated requests, manager on leave, policy change mid-year, and an edit after approval. If the outcome surprises HR, the rule is not clear enough yet.
Calendar integration that stays accurate over time
A calendar should answer one question fast: who is out, and when. Don’t try to turn the calendar event into the whole request record. Put only what helps scheduling, and keep the rest inside your HR system.
For event content, keep it consistent. A good default is a short title like “Out of office - Alex Kim” plus the leave type if it matters (“PTO”, “Sick”). Keep details minimal for privacy. Many teams prefer showing the event as “Busy” and storing reasons, balances, and notes only in the request.
Treat calendar events as a mirror, not the source
Every request needs a stable internal ID, and every calendar event should store that ID (for example in a custom field or description). That way you can safely create, update, and delete the right event when requests change.
Handling status is where systems drift. Decide upfront whether tentative requests appear at all. If you do show them, make the difference obvious (for example, title prefix “Pending” and a different availability setting). When a request is approved, update the same event rather than creating a new one. If a request is cancelled or rejected after being visible, delete the event so calendars do not lie.
Time zones and “weird” days
Time zones bite hardest with all-day and partial-day leave. Store start and end as exact timestamps in the employee’s local time zone, and also store that time zone on the request.
Use all-day events only for true full-day leave. For partial days, create timed events (for example 13:00-17:00) so colleagues in other zones see the correct overlap.
- Full day: all-day event in the employee’s time zone
- Partial day: timed event with start and end timestamps
- Multi-day: all-day events are fine, but double-check the end date rule (inclusive vs exclusive)
If calendar sync fails, don’t hide it. Queue the job, retry with backoff, and show a clear “Calendar not updated” status with a manual “retry sync” action. In tools like AppMaster, this is usually a simple background process plus an admin screen listing failed sync attempts so HR can fix issues without editing requests.
Common mistakes and how to avoid them
Most failures in time-off request system design happen when the rules grow quietly over time. The system still “works”, but no one trusts the balances, and every odd case becomes a support ticket.
Mistake 1: Accrual logic buried in exceptions
If accrual is split across many special cases (new hires, carryover, unpaid leave, part-time), people cannot predict their balance.
Keep one clear accrual model per leave type, then add exceptions as named, testable rules. Write down a few sample employees and expected balances for specific dates, and re-check them whenever policies change.
Mistake 2: Approval flows that fork forever
Endless branching approvals become impossible to test, and managers do not know why a request went to someone else.
A safer pattern is:
- One default approver (usually the direct manager)
- One optional second approver (HR or department head) based on simple conditions
- One clear fallback when the approver is out (delegate or next manager)
- One final state per request (approved, rejected, canceled)
Mistake 3: Mixing policy text and math in one field
Policy text is for humans (what counts, who is eligible). Math rules are for the system (rate, caps, rounding, carryover). Store them separately so you can update wording without changing calculations, and test calculations without rewriting the handbook.
Mistake 4: Edits and cancellations are not recorded
If you overwrite requests, you lose the “why” behind a balance change.
Always keep an audit trail: who changed what, when, and the previous values. In AppMaster, this is straightforward to model as a request history table plus status transitions in a Business Process.
Mistake 5: Time zones and holidays are an afterthought
Time-off spans dates, but approvals and calendar entries use timestamps. Normalize to a single “policy time zone” and store the employee’s local time zone too. Also decide early whether public holidays reduce the requested days, and apply that rule consistently.
Quick checklist before you roll it out
Before you announce it to everyone, run through a short set of checks with a real employee, a manager, and someone from HR. You want to confirm the system feels obvious, not just that it works.
Use this checklist as a go/no-go gate for your time-off request system design:
- Balance visibility: An employee can see today’s balance and how upcoming approved time off changes it (so they do not “discover” a negative balance later).
- Policy clarity: Every rule is written in plain language (carryover, blackout dates, minimum notice, half-days) and the logic matches those words exactly.
- Helpful validations: When a request is blocked, the message says what to change (dates, leave type, hours, missing attachment), not just “error” or “not allowed.”
- Manager-ready approvals: A manager can approve from one screen with enough context (remaining balance, overlapping team absences, handoff notes) and can request changes without a long back-and-forth.
- Calendar and audit: Calendar events are created and kept in sync on approve, change, and cancel, and every status change is logged with who did it and when.
A quick, practical test: create one request, approve it, edit the dates, then cancel it. If any step leaves behind a wrong balance, a stale calendar event, or an unexplained status, fix that before launch.
If you’re building this in AppMaster, keep the workflow readable by naming each step after the user action (Submit, Validate, Route to Manager, Update Balance, Create/Update Calendar, Log Event) so the behavior stays clear as policies evolve.
Example scenario: from request to calendar invite
A new hire, Maya, starts on March 10. Your time-off request system design supports monthly accrual, so Maya earns PTO on the first of each month. On April 12, she requests a partial day off: 3 hours next Friday for a medical appointment.
What each person sees is different:
- Employee (Maya): current balance, how many hours this request will use, and a clear warning if it would go negative.
- Manager: a short summary (date, hours, coverage note) plus the option to approve, deny, or delegate.
- HR: the policy used for the calculation, an audit trail, and a way to recalc if rules change.
Maya submits the request. Her manager is on vacation, so the system checks the delegation setting and routes it to the acting manager. The acting manager approves.
At approval, two things happen: the request is locked to the policy version used, and a calendar event is created for “Maya - PTO (3h)” on the correct date and time window. Maya immediately sees “Approved” and the calendar status “Added.”
In June, HR updates the policy mid-year (for example, accrual increases after 90 days). Balances need recalculation, but past approved requests should not be silently changed. The system recalculates Maya’s current balance from the effective date forward, keeping an audit record of before/after values.
A week later, Maya edits the request date (the appointment moved). Because the leave was already approved, the change becomes a new “Change request” that goes back to the delegated approver. Once approved again, the existing calendar event is updated (same event ID), not duplicated.
This is easy to model in a tool like AppMaster by keeping the workflow readable: one approval path, one delegation check, one calendar create/update step, and a separate recalculation action HR can run when policies change.
Next steps: ship the first version and iterate safely
The safest way to finish a time-off request system design is to ship a small version that people can trust, then expand. Start with one policy (for example, PTO) and one approval path (employee -> manager). Once that feels boring and reliable, add the next policy type, region, or edge case.
Before you build more rules, decide where the source of truth lives. If your HR system is the master record, your app should mostly validate, route approvals, and sync results back. If your app is the master, you need clearer audit logs and a plan for what happens when HR data changes (new manager, department moves, termination dates).
A practical first release plan:
- Implement one leave type with a clear balance and a single accrual rule.
- Add one manager approval step and one HR override path.
- Create a simple calendar sync for approved time off only.
- Keep an admin screen where policy settings are readable by non-technical owners.
- Add basic reporting: who is out, and upcoming absences.
Write down 5 to 10 real test cases and rerun them after every change. Use cases from your own team, not made-up examples. For instance: someone requests Friday off on Thursday, someone changes their request after approval, or a manager approves while the employee is on a different time zone.
If you build with no-code, visibility matters as much as features. In AppMaster, you can keep the data model (leave types, balances, approvals) and the approval workflow in visual editors, so HR and ops can review what the system actually does. You can also expose APIs for calendar sync and regenerate clean source code as policies evolve, without stacking messy fixes over time.
When the first version is stable, expand one dimension at a time: more policies, more routing rules, then more integrations.


