Five Executables, One Database — the Reckoning
The honest ledger for the whole estate - what coordinating through tables actually cost, what genuinely earned its keep, and what I would reach for now instead of using the database as a message bus.
Newest first, grouped by year. Search or filter by topic.
The honest ledger for the whole estate - what coordinating through tables actually cost, what genuinely earned its keep, and what I would reach for now instead of using the database as a message bus.
The same dashboard KPI is computed by three different formulas across role-variant procedures, rendered on a gauge with a sibling metric quietly deleted - and the fact table beneath it is an accidental Kimball star nobody designed.
The business month runs the 16th to the 15th, so a year-overview proc carries twelve correlated subqueries, five-day-capped weeks, time averaged through float casts and contractor filters that drift by a digit between copies.
One hierarchy, three implementations - a recursive CTE, a view that calls a scalar function on every row, and a whole family of tree procs - plus a relationship flag that is a decimal number pretending to be binary.
Thirty-eight tables, fourteen foreign keys, none on the tables that need them - plus a shipped SSMS template index, auto-tuning suggestions accepted blind, three-state booleans and a demo mode that mutates production master data.
The same database solves the same sortable-paging problem twice - once by concatenating user input straight into EXEC, once with a CASE whitelist, QUOTENAME and sp_executesql. A side-by-side of the wrong and right answer.
UTC timers, IST badge gates, DateTime.Now in one executable and UtcNow in the next, columns that record neither - how a system whose entire product is timestamps got away with never deciding what time it is.
Every five minutes a function hunts for people still virtually swiped in past ten hours and emails them - magic node numbers, an at-most-once flag with a gap in it, and a local config file pointing straight at production.
A 22-character job name, a 20-character column, and an error handler that has thrown on every attempt since the day it shipped - plus the four parallel logging systems that still could not catch it.
When one job needs another to redo work, it leaves a row - an action enum, a rewind date and a Done flag standing in for a message broker, plus the delete-and-replay proc that makes reruns possible.
Four magic strings in an audit column decide which rows the batch jobs may overwrite and which belong to humans - provenance, workflow state and inter-job protocol smuggled into a field meant for names.
The shift calculator writes one report row per employee per day since 2019, inventing blank rows for days nobody badged - a dense date spine built from sentinel values, at the price of one database round-trip per row.
Reflection that builds EXEC statements, a table-valued function called by string interpolation, and a raw ADO.NET runner returning lists of lists - one codebase, three coexisting answers to the same question.
Badge gates record when you arrived, not which shift you worked - so the platform infers it, scoring every candidate shift by L1 distance in time-of-day space and letting the smallest number win.
Leave records arrive late, change and get cancelled - so the sync reaches back into already-approved attendance rows and re-derives them, carefully stepping around human decisions and allowance money.
The leave sync resumes from wherever its own job log last said Success - one table serving as log, watermark and metrics store at once, with recursive pagination on top and an envelope check in exactly the wrong place.
A daily Azure Function mirrors the HR system's employee master into the attendance database - a field-by-field upsert, a clever delegation rule, a vestigial handshake, and the parse calls that can kill the whole run.
Five executables, zero queues - how an attendance platform coordinated a web app, three Azure Functions and a console job through one SQL database, and what that choice bought and cost. Part 1 of the series.