← All work

Our Product · SaaS / Workforce Management

Alectryon

Time tracking, scheduling, and time-off that feeds payroll

alectryon.io →

43

domain entities

8

history-tracked tables

Per-seat

self-service billing

QuickBooks

accounting sync

The Problem

Time tracking looks trivial until it touches payroll, and then it is a legal record. Small teams run on spreadsheets and a supervisor's memory, which works right up to the first disputed paycheck, the first time-off balance nobody can reconcile, or the first audit that asks who changed that entry and when. The products that handle it properly are priced for enterprises.

The Approach

  1. 1

    Treat edited time as the interesting case. Every time entry modification writes to a modification log, and time-off balances, requests, types, and job-position entitlements all carry parallel history tables, so 'what was this balance in March, and who changed it' is a query, not an investigation.

  2. 2

    Model accrual as policy rather than arithmetic. Accrual types, time-off types, per-job-position entitlements, and per-user overrides are configured data, because every organization's leave policy is slightly different and none of them want a code change to express it.

  3. 3

    Own the commercial side of the product too. Subscriptions, pricing tiers, payment logging, and cancellation with structured cancel reasons and feedback are part of the system. A SaaS product without self-service billing is a demo with an invoice attached.

  4. 4

    Push periodic work to timer-triggered Azure Functions (accrual runs, queued email, scheduled processing), so tenant-facing request latency is unaffected by background load.

  5. 5

    Separate the layers so the domain stays testable. Domain, data access, application services, and API are distinct projects with dependency injection configured in its own assembly, and the service and validation layers carry their own test suites.

What It Does

  • Clock in and out with time entry types, supervisor adjustment, and a full modification log
  • Shift scheduling against job positions and job functions
  • Time-off requests with approval workflow, status history, and per-type balances
  • Accrual engine driven by configurable accrual types and per-position entitlements
  • Client and project time allocation, with client contacts and billable time entries
  • Timesheet aggregation and PDF generation for payroll handoff
  • QuickBooks Online integration for pushing time and invoice data into accounting
  • Self-service subscription billing via Authorize.Net, with tiered pricing and structured cancellation feedback
  • Multi-tenant organizations with role-based access and per-tenant settings
  • Password policy enforcement including a blacklist check, plus generated memorable passwords for onboarding

Engineering Decisions

The choices worth defending in a technical conversation, and why they were made.

History tables, not audit-by-timestamp-column

Time-off balances, requests, types, and entitlements each have a dedicated history table. A modified-date column tells you something changed; a history row tells you what it was before, which is the only version that helps in a payroll dispute.

Layered architecture that earns its layers

Domain, data access, application services, DI configuration, and API are separate assemblies with their own test projects. The separation exists so business rules can be tested without a database, and it is used that way rather than being decorative.

Payroll-adjacent means correctness over cleverness

Timesheet aggregation feeds real paychecks. This is the part of the system where the boring, explicit, heavily-tested implementation is the correct engineering choice, and where a clever abstraction is a liability.

Secrets and keys out of configuration

Azure Key Vault backs the configuration provider, with BouncyCastle handling cryptographic operations and BCrypt for password hashing. Nothing sensitive resolves from an appsettings file.

The Stack

Backend

.NET 8ASP.NET CoreEntity Framework Core 9SQL ServerFluentValidationAutoMapper

Frontend

React SPASeparate signup application

Commerce & integrations

Authorize.Net subscriptionsQuickBooks Online APIPDFsharp timesheetsPostmark email

Platform & security

Azure Functions (timer-triggered)Azure Key VaultAzure Blob StorageJWT with refresh tokensBCryptBouncyCastle

Want something like this built?

Let's talk about what you're building and how we can help.