TerkAge

TerkAge Terk-Age Technologies helps organizations turn inefficient manual processes into practical digital systems.

24/08/2026

Don't tell people your software is powerful. Show them.

Here's a look inside one of the systems we're building.

Registration.
Clinical workflows.
Pharmacy.
Laboratory.
Reporting.

The goal isn't to create another complicated application.

It's to make the work easier.
Facebook Hugging Face LinkedIn

This is what software development actually looks like.Not just writing code.Meetings.Requirements.Workflow mapping.Testi...
23/08/2026

This is what software development actually looks like.

Not just writing code.
Meetings.
Requirements.
Workflow mapping.
Testing.
Feedback.
Bugs.
Redesign.
More testing.
And sometimes going back to the drawing board.

The final application is only the visible part.
The thinking behind it is where most of the work happens.
Facebook LinkedIn

Here's what nobody tells you about building hospital software.A patient is one person……but six departments see six diffe...
18/08/2026

Here's what nobody tells you about building hospital software.

A patient is one person…
…but six departments see six different stories.

👨🏽‍⚕️ Doctor → Diagnosis

👩🏽‍⚕️ Nurse → Care

💊 Pharmacy → Medication

🧪 Lab → Results

💳 Finance → Payment

📋 Records → History

The real challenge isn't building six modules.
It's making them work as ONE patient journey.
That's where good digital health gets difficult—and interesting.

Which hospital department do you think is hardest to digitize? And why?

Facebook

17/08/2026

We’ve all been there… 😅

Looking for one document among a mountain of files.

Sometimes the problem isn't the people.

It's the process.

Let’s build systems that make work easier—not more complicated. 🇳🇬

Facebook LinkedIn

A feature isn't valuable because it exists.It's valuable because it solves a problem.That's one principle guiding how we...
15/08/2026

A feature isn't valuable because it exists.

It's valuable because it solves a problem.

That's one principle guiding how we build software at Terk-Age LTD.

Instead of asking:

"What features should we add?"

We ask:

"What problem are we trying to eliminate?"

That's how we avoid building complicated software nobody wants to use.

Facebook OpenMRS Management Sciences for Health

What if your hospital could finally see the whole patient journey in one place?A patient walks into a hospital.Registrat...
11/08/2026

What if your hospital could finally see the whole patient journey in one place?

A patient walks into a hospital.

Registration.

Consultation.

Laboratory.

Pharmacy.

Billing.

Admission.

Discharge.

Today, these activities can easily become disconnected across departments, paper folders, spreadsheets and different systems.

That creates one major problem:

The hospital has data—but not necessarily visibility.

A modern HMIS should connect the journey.

One patient.

One longitudinal record.

Connected departments.

Real-time information.

Better decisions.

And with standards such as HL7 FHIR, healthcare systems can be designed to communicate—not operate as isolated islands.

At Terk-Age Technologies, we believe African healthcare technology should be built around the people using it:

Doctors. Nurses. Pharmacists. Laboratory scientists. Records officers. Administrators. And, most importantly, patients.

Digital transformation isn't about putting computers in hospitals.

It's about making healthcare work better.

What would you digitize first in a hospital?

Facebook

Every hospital system needs a local outbox — a queue that captures transactions when the network is down.The easy choice...
04/08/2026

Every hospital system needs a local outbox — a queue that captures transactions when the network is down.

The easy choice is Redis. Fast, in-memory, battle-tested. The default for sync pipelines everywhere.

We chose SQLite. Here’s why, and why it matters for a hospital in Nigeria.

🏥 Redis is a memory cache. It's fast. It's also volatile — reboot the server, the data disappears. In a hospital, "data disappears when the server reboots" isn't a bug. It's a patient safety event.

📋 SQLite is a local file. It's ACID-compliant. It's durable. If the server loses power, the outbox survives. If the network drops for 17 minutes while a nurse is registering a patient, the transaction stays queued on disk — not in a memory structure that vanishes with the next restart.

🔧 The PL/pgSQL trigger writes to sync_queue — not Redis. Every INSERT, UPDATE, and DELETE on every clinical table (patients, encounters, observations, medication_requests) automatically writes a row into sync_queue via a PostgreSQL trigger function. The payload is JSONB. The record ID handles compound primary keys (for junction tables like user_role_mappings). The status starts as PENDING. A background LISTEN sync_queue_channel picks it up immediately

The key insight: the trigger runs inside PostgreSQL itself. It's not an application-level callback that can fail silently. It's not a network call to Redis that can drop if the Redis server restarts. It's a database-level guarantee — if the write succeeds, the sync queue entry is committed atomically.

📊 SQLite isn't a cache. It's a transaction log. When the hospital's generator cuts out and the server shuts down, the sync_queue table still has every pending transaction on disk. When power returns, the sync engine picks up exactly where it left off: SELECT ... FROM sync_queue WHERE status IN ('PENDING', 'FAILED') AND attempts < 3.

Redis would lose everything. SQLite keeps it all.

The tradeoff we accepted: SQLite isn't as fast as Redis for simple key-value lookups. For a sync outbox, that's fine — durability matters more than single-digit millisecond latency. If a transaction takes 5ms instead of 1ms, but survives a power failure, we'll take the 5ms.

Why this matters for Nigerian healthcare: A Redis-based sync queue fails silently in Nigeria. A SQLite/PostgreSQL trigger-based queue fails visibly — and the team can see the pending entries in the outbox, count them, and know exactly what needs to catch up when the network returns.

We didn't pick the faster option. We picked the durable one.

If your sync pipeline uses an in-memory queue for a hospital system — you already know what happens when the server reboots. ♻️ Share this with your Infrastructure Lead.



HL7 Europe HIMSS World Health Organization UNICEF UNAIDS The Global Fund SNOMED International

Every health-tech startup picks a data layer early. Most pick cloud-first. We picked local-first.It wasn't the obvious c...
03/08/2026

Every health-tech startup picks a data layer early. Most pick cloud-first. We picked local-first.

It wasn't the obvious choice. Cloud databases promise auto-scaling, zero management, global replication. They sound perfect. Until you're in a Nigerian hospital at 6am and the generator cuts out for 17 minutes.

Here's what's running in our stack — and what each layer actually owns:

🟢 Primary database (local server room). PostgreSQL running on physical hardware in the hospital server room. Every transaction writes here first. Every query hits this first. It's the authoritative copy — the source of truth during normal operations.

🟡 Standby database (warm backup). A second PostgreSQL instance that mirrors the primary in real-time. If the primary goes down, failover is automatic — connectionManager.ts health-checks every 10 seconds and flips to the standby within 2 failures. The switch is invisible to users.

🔵 Cloud database. A managed PostgreSQL that receives real-time replication from the primary. It's the remote backup — accessible from any device, anywhere. But it's not authoritative during local operations.

⚫ Offline capture (device-local SQLite). When both the primary, standby, and cloud are unreachable, the device captures transactions in a local SQLite queue. These transactions are replayed when any upstream layer comes back online.

The decision flow — automated, continuous, zero user intervention:

connectionManager.ts runs every 10 seconds, probing all layers.

If Primary responds → it stays active. Local writes continue.

If Primary fails → Standby takes over automatically. runWithRetry in prisma.ts handles the handoff.

If Standby also fails → Cloud becomes the active layer. The system continues in cloud-fallback mode.

If Cloud also fails → Device captures offline. Queue grows in local SQLite.

When any upstream layer recovers → reverseSyncFromCloud() automatically pulls down any cloud-captured records back to the local database.

The tradeoff we accepted: Local-first means more infrastructure to maintain. Three database layers instead of one. Conflict resolution logic that most SaaS vendors never write. A sync engine that handles offline capture, conflict detection, and reverse-sync reconciliation.

But it means the system works when the network doesn't.

Why this matters for Nigerian healthcare: A cloud-first system fails silently in Nigeria. A local-first system fails visibly — and the team can see the failover in action, understand it, and keep working.

We built a system that fails forward, not backward.

If your hospital's data layer has a single point of failure — you don't have redundancy. You have risk. ♻️ Share this with your Infrastructure Lead.

Facebook
UNAIDS

Every health-tech vendor says: "Use Auth0. Use Okta. Use Cognito. It's industry standard."Industry standard is fine — if...
01/08/2026

Every health-tech vendor says: "Use Auth0. Use Okta. Use Cognito. It's industry standard."

Industry standard is fine — if you want a system that works like everyone else's.

We chose a different path. We built our own authentication layer from scratch. Here's why, and what it actually looks like in the code:

🔐 Custom bcrypt password hashing — 12 rounds. Every password in the Terk-Age HMIS gets hashed with bcrypt at 12 rounds. That's the same level of security Auth0 and Okta provide — but it's ours. We control the salt, the rounds, the algorithm. No vendor decides to lower the security bar for cost savings.

🔑 JWT access tokens + refresh tokens — our own rotation. Access tokens expire in 15 minutes. Refresh tokens expire in 7 days. When a refresh token is used, it's deleted and a new one is issued — no token reuse, no replay attacks. The JWT_SECRET and REFRESH_TOKEN_SECRET are environment variables, not hardcoded strings.

🛡️ TOTP authenticator app — built on speakeasy. We use speakeasy for TOTP generation and verification — the same library Auth0 uses under the hood. But we control the enrollment flow, the QR code generation, the secret storage. Every 30-second code is single-use. Codes can't be replayed within 90 seconds.

📧 Email OTP fallback — our own implementation. If a user doesn't have an authenticator app, they get a one-time code via email. It's not a "forgot password" flow — it's a second authentication path, equally secure.

🚪 LAN break-glass code — for when everything else fails. In a hospital, a doctor can't wait for an email OTP during a code blue. The break-glass code lets them through — but every single use is logged with action: 'auth.mfa_break_glass_lan', including who, when, and what they accessed.

📱 Device trust — once verified, less friction. The first time you log in on a new device, 2FA fires. After that, the system remembers that device via a trustedDeviceToken. Dr. Adesanmi doesn't enter a code every morning — just once per device, then smooth sailing.

🔄 Password history — last 5 passwords blocked. passwordPolicy.ts checks the last 5 password hashes before allowing a change. You can't reuse your old password. Ever. The isPasswordReused function compares against passwordHistory records and the current active hash.

🔍 Full audit trail — every auth event logged. Every login, every failed attempt, every password change, every break-glass access — logged via logAudit() to the auditLog table with userId, action, resourceType, ipAddress, userAgent, and changes. The audit logs are excluded from sync replication (they stay local) and are append-only.

The tradeoff we accepted: Building custom auth means more code, more maintenance, more responsibility. No vendor support line to call when something breaks. No monthly per-seat fee that scales with every new staff member. No "we'll deprecate that feature next quarter" surprise.

But it means we own every line of the security stack.

Every health-tech vendor I talk to says the same thing: "Our system is cloud-native. Real-time sync. Always connected."T...
29/07/2026

Every health-tech vendor I talk to says the same thing: "Our system is cloud-native. Real-time sync. Always connected."

That sounds impressive in a demo. It sounds less impressive at 6am on a Tuesday when the hospital wifi drops because someone unplugged a ceiling tile for cleaning.

Here’s the decision we made early — before a single line of frontend code — that changed everything:

We built local-first. Not cloud-first.

🏗️ What most vendors build: A cloud database as the single source of truth. Every transaction must reach the cloud before it’s considered “saved.” If the network blinks, the system freezes. If the cloud is slow, the UI is slow. If the hospital is in a rural Nigerian town with a rooftop antenna and a diesel generator, the system is unusable for 40% of the day.

🏗️ What we built instead: A local SQLite database on every device as the source of truth. The cloud is a replica, not the authority. Every transaction writes to the local device first — always. The cloud receives changes later, in order, automatically.

The result is visible in three places in the codebase:

📦 syncService.ts — the local outbox. Every write goes to a sync_queue table before it touches the cloud. If the cloud is unreachable, the queue grows. If the cloud comes back, the queue drains. Zero data loss. Zero duplicates.

🔁 setupTriggers.ts — database-level triggers. Every INSERT/UPDATE/DELETE on critical tables automatically writes a row into sync_queue. The application doesn’t have to remember to sync. The database enforces it at the PL/pgSQL level.

🛡️ prisma.ts auto-failover — the runWithRetry helper reads getLayer() and automatically falls back from PRIMARY → STANDBY → CLOUD → OFFLINE. The user never sees “failover triggered.” They see a system that keeps working.

📱 SystemStatusBadge.tsx — the UI tells the truth: “Records captured offline on device — will sync when restored.” No spinner. No “please wait.” No shame.

Why this matters for Nigerian healthcare: A hospital in Abuja has the same network reliability as a hospital in a rural LGA. Generator fuel fluctuations. Rooftop antenna rain fade. NEPA “taking light” at random. A cloud-first system treats these as exceptions. A local-first system treats them as Tuesday.

The tradeoff we accepted: Local-first is harder. Conflict resolution is harder. Data consistency across devices is harder. Sync ordering is harder. We wrote more code to handle the edge cases than most vendors write for the happy path.

But the alternative is a system that works perfectly in a demo room and fails perfectly in a real hospital.

We didn’t want perfect demos. We wanted a system that works at 6am on a Tuesday, when the network is down and a nurse needs to register a patient before the doctor’s round starts.

If your hospital system stops working when the wifi does — it’s not a system. It’s a screen with a lock.

Facebook

Address

House 10, Road 3, Pengassan Phase One Lokogoma
Lugbe
900107

Alerts

Be the first to know and let us send you an email when TerkAge posts news and promotions. Your email address will not be used for any other purpose, and you can unsubscribe at any time.

Contact The Business

Send a message to TerkAge:

Shortcuts

Share