Smart Office Platform · Tech Heart (Tini Group), 2024–2025

Multi-tenant smart office backend with IoT access control

One backend decides who may open which door — by smart lock, fingerprint, or card reader — and buildings keep a predictable rule when the network drops. A later change of product direction reused that foundation instead of rebuilding it.

NestJS · PostgreSQL · MongoDB · Docker

Result: First product shipped in about 2 months with scope cut; team of 9 onboarded with mandatory review; platform pivot without re-architecting identity.

The problem

A new company needed a multi-tenant backend for buildings, doors, and people, with IoT readers that must still decide access when the network is unreliable.

Team mostly new hires; consistency had to come from repo structure, not long written standards.
First product shipped in two months; scope had to be cut, not inflated.
Later pivot to smart office could not throw away identity and tenant work.
Door commands must not double-execute on timeout and retry.

System architecture

flowchart LR
  subgraph control ["Control plane"]
    control_0["NestJS APIs"]
    control_1["Tenant and permission service"]
    control_2[("PostgreSQL transactional data")]
  end
  subgraph devices ["Devices"]
    devices_0(["Smart lock / reader"])
    devices_1["Permission snapshot on device"]
    devices_2["Idempotent door command handler"]
  end
  subgraph flex ["Flexible payloads"]
    flex_0[("MongoDB device documents")]
  end
  control_0 --> control_1
  control_1 --> control_2
  control_1 --> devices_2
  devices_2 --> devices_0
  control_1 --> devices_1
  devices_0 -->|"telemetry"| flex_0

Key architecture decisions

Server is source of truth; device holds a snapshot

Access decisions are computed on the server; devices keep a permission snapshot for offline intervals.

Operators cannot revoke access in real time if the device only trusts its last full sync forever.

Rejected Device-only ACL with no expiry — rejected for security review on building egress.

Trade-off Snapshot TTL and reconciliation when the device comes back online.

Idempotent door commands

Every open command carries a unique command ID, so a retry after a timeout is recognised as the same command and cannot create a second physical open.

Mobile and gateway retries are normal; actuators are not.

Rejected Fire-and-forget HTTP to lock firmware — rejected after duplicate-open reports in testing.

Trade-off Command store or cache to remember accepted keys for a window.

PostgreSQL plus MongoDB by shape, not hype

PostgreSQL for tenant, people, doors, and transactional permissions; MongoDB for variable device payload documents.

Relational invariants for who may open what; flexible documents for vendor-specific telemetry.

Rejected Mongo-only for everything — rejected when relational reporting was required week one.

Trade-off Two stores to backup and monitor; clear ownership of which API touches which store.

What I own, wrote, and delegate

Own

  • CI/CD, review rules, branching, and initial backend architecture
  • Pivot plan that kept tenant, auth, and service boundaries

Wrote

  • NestJS multi-tenant APIs and permission model for access decisions
  • Onboarding path: one vertical slice per new engineer in week one

Delegate

  • Mobile UI after API contracts were stable
  • Chain integration on the company's first product

Scale

  • Initial engineering team of 9 across backend, frontend, and mobile
  • Concurrent with InnoVerse from 08/2024; InnoVerse became the primary role
  • The smart office platform was still in production when I last had visibility

Boundaries

  • The two-month release was the first product, a blockchain real-estate platform. This case is the access-control backend after the pivot, on the same platform.
  • Reader protocol, and fail-safe versus fail-secure, are chosen per door at the site.

What we watch in operation

Door command duplicate rateDevice offline duration versus snapshot ageWeekly release cadence after CI standardisation

Rules the design never breaks

  • No command is sent without a resolved tenant and permission check on the server.
  • Pivot removes domain tables, not tenant or identity modules.
  • Mandatory review before merge to the release branch.

Broader application

  • Greenfield teams that need structure before they need features.
  • Access control where offline devices still need a predictable policy.
  • Product pivots that must reuse security foundations.