Skip to content

IllustrativeThis is an illustrative engagement scenario, not a named client case study.

//Legal & Immigration · Software Development

Building a legal case management system a law firm can put privileged matters into

A reference build for legal case management: a matter data model that separates entities, matters and party roles, conflict checking built into matter opening, privilege-aware access control, and an append-only audit trail — sitting beside practice management, not replacing it.

01The challenge

A law firm needs to move privileged, deadline-bound matters into custom software without losing a limitation date, missing a conflict, or losing the ability to prove who accessed a file.

02What we did
  • 01Modelled entities, matters and party roles separately so conflict checking and privilege could be enforced at the data layer.
  • 02Built conflict checking into matter opening, returning a two-tier result that flags a conflict without disclosing the confidential matter behind it.
  • 03Made privilege and access control explicit — matter team membership, ethical-wall exclusions, and document-level privilege flags, evaluated in order.
  • 04Built the audit trail as an append-only event log, and phased rollout by practice group instead of a single cutover.

The question this engagement had to answer

*Can a firm move live, privileged, deadline-bound matters into custom software without losing a limitation date, a conflict, or the ability to prove who saw what?*

Firms of this size sit in a specific trap. Off-the-shelf practice management handles time, billing and basic matter records, and handles them adequately. It does not handle the firm's actual work — the immigration application with 40 evidence items and a government portal deadline, the client with six related matters across two entities, the paralegal workflow that currently lives in a spreadsheet and one person's memory.

So the firm bolts spreadsheets onto the practice management system. That works until someone leaves.

What was hard

The tradeoff: replace practice management, or sit beside it. The tempting scope is to replace everything, including time recording and billing. We reject that. Billing is regulated, deeply embedded, integrated with the firm's accounting, and replacing it puts revenue collection at risk to solve a problem that is not about billing. The build sits beside practice management and integrates. It owns matter workflow, documents and evidence. Practice management keeps owning client records, time and billing, and remains the system of record for both. That decision costs us. Integration is harder than ownership, reconciliation is a permanent obligation, and two systems can disagree. We take that cost because the alternative risks the firm's cash collection.

The rejected alternative: one flat "case" record. Almost every first draft of a legal data model has a case with a client, a status and a set of documents. It breaks within a month. A client is not a person — it can be a company, a family group, or an individual who is also a director of a corporate client. A matter has multiple parties with different roles, some of whom are adverse. Documents belong to a matter, but privilege attaches to the communication, not the folder.

What broke: our first retention implementation. We built retention as a scheduled deletion job against a retain_until date. It was wrong in a way that took a real file to expose. Retention periods restart on events — a matter reopening, a complaint, a regulatory hold — and destruction must be suspended entirely when litigation is reasonably anticipated. A job that deletes on a date will eventually destroy something under hold. We rebuilt it as an event-driven schedule with hard legal-hold blocking and a two-person approval before any irreversible destruction.

Deadlines are the real risk surface. In immigration and litigation work, a missed date is a negligence claim. Any feature touching dates gets treated as safety-critical, not as a convenience.

What we did

1. Modelled matters, parties and relationships properly. The core model separates four things that flat systems collapse into one. Entity — a person or organisation, existing once across the firm, regardless of how many matters they touch. Matter — the unit of work, with a matter type, a responsible fee earner, a jurisdiction and a lifecycle state. Party role — the join between an entity and a matter, carrying the role: client, opponent, dependant, sponsor, witness, third party, intermediary. Adverse roles are flagged at this layer, which is what makes conflict checking possible. Task and deadline — hung off the matter, with a source (statutory, court-ordered, internal) and an owner. Matter types carry their own required fields and evidence checklists. An immigration application matter demands items a probate matter does not. This is the part that makes immigration software different from generic law firm software: the checklist is the work.

2. Built conflict checking into matter opening, not alongside it. Conflict checking runs at three moments: enquiry, before engagement, and whenever a new party is added to an existing matter. It searches entities, former names, trading names, related corporate entities, and previously closed matters — including matters the searching user has no permission to open. That last point is the design problem. The search must surface that a conflict exists without disclosing the confidential matter causing it. So results return at two levels: a hit visible to the searcher showing that a potential conflict exists and who must clear it, and full detail visible only to the conflicts team or the responsible partner. The clearance decision, its reasoning and the approver are stored permanently on the matter.

3. Made privilege and access control explicit rather than role-based. Role-based access alone is not sufficient in a law firm. Two things break it: information barriers between teams acting on opposite sides, and privileged communications that must stay narrower than the matter team. Access resolves through three layers, evaluated in order: matter team membership, an ethical-wall exclusion that overrides membership, and a document-level privilege flag that narrows visibility further within the team. A privileged advice note is visible to the responsible partner and the named fee earners, not to everyone with matter access. Break-glass access exists, because emergencies exist. It requires a stated reason, it notifies the responsible partner immediately, and it is written to the audit log as a distinct event type.

4. Built the audit trail as an append-only event log. Every read of a document, every access grant, every field change, every deletion, every break-glass event. Append-only, no update path, no delete path, retained beyond the matter's own retention period. This is not a compliance checkbox. It is the artefact the firm produces when a client asks who saw their file, when a regulator asks how a conflict was cleared, or when an insurer asks what happened before a claim. If the audit trail is reconstructible from application logs rather than stored as first-class events, the answer is not defensible.

Architecture

flowchart TB
    subgraph Client["Fee earner + paralegal"]
        UI["Web app<br/>matter workspace"]
    end
    UI --> GW["API gateway<br/>authn + session"]
    GW --> AUTHZ["Authorization service<br/>matter team + ethical wall + privilege flag"]
    AUTHZ --> MAT["Matter service<br/>entities, parties, roles, lifecycle"]
    AUTHZ --> DOC["Document service"]
    AUTHZ --> CONF["Conflict check service"]
    AUTHZ --> DEAD["Deadline + task service"]
    MAT --> DB[("Postgres<br/>matters, entities, party roles")]
    CONF --> DB
    CONF --> IDX[("Search index<br/>names, aliases, former names")]
    DOC --> S3[("Encrypted object store<br/>versioned, immutable objects")]
    DOC --> RET["Retention engine<br/>event-driven schedules"]
    RET --> HOLD{"Legal hold<br/>active?"}
    HOLD -->|"yes"| BLOCK["Destruction blocked<br/>logged"]
    HOLD -->|"no"| APPR["Two-person approval<br/>then destroy"]
    DEAD --> NOTIF["Notification + diary service"]
    MAT <-->|"sync: clients, matter numbers"| PMS["Practice management system<br/>time + billing, system of record"]
    DOC -.-> AUDIT[("Append-only audit log")]
    MAT -.-> AUDIT
    CONF -.-> AUDIT
    AUTHZ -.-> AUDIT
    RET -.-> AUDIT
Architecture diagram — Mermaid source (not rendered)

The authorization service sits in front of everything. No service is reachable without an access decision, and the decision is one code path, not a check repeated in each service. A permissions model implemented four times is a permissions model with four different bugs.

Documents are immutable and versioned. A new version creates a new object. Nothing is overwritten, because a document that changed without a record of the change is a document that cannot be relied on in a dispute.

Practice management stays the system of record for clients, matter numbers and billing. The integration syncs both ways on a defined field set, with a nightly reconciliation report naming every divergence. We assume the systems will disagree and make disagreement visible rather than pretending it cannot happen.

How we evaluated it

The eval set. Twenty to forty real, anonymised matters supplied by the firm, spanning the messiest cases they have: a client who is also a director of an opposing company, a matter reopened after closure, a family group with shared and separate matters, a matter with a document under legal hold, a matter with a statutory deadline that moved. Every one is loaded into the system and every one must model cleanly without a free-text workaround. A matter that only fits in a notes field is a data model failure, and we find those before rollout.

The metric that mattered: conflict-check recall. Not precision. We measure recall against a set of known historical conflicts the firm has already identified, and we require that the system catches every one. False positives cost the conflicts team minutes. A false negative costs the firm a matter, a client and possibly a claim. We tune aggressively toward over-flagging, including fuzzy and phonetic name matching, and we accept the review burden.

The second measured number is deadline integrity: every statutory or court deadline in the migrated set present, correct, owned by a named person, and firing its reminders. This is checked by reconciliation against the old diary, item by item, not by sampling.

Latency where it is felt. Two interactions are gated on p95: matter workspace load and document open. Fee earners abandon a system that is slower than the shared drive, and adoption failure is the most common way legal software dies. Conflict checks run asynchronously with a visible progress state, because thoroughness matters more than speed there.

Failure modes and what happens when the system is wrong.

*A conflict is missed.* Containment: conflict checking is one of three controls, not the only one — matter opening still requires partner sign-off, and every clearance decision is logged with reasoning so a missed conflict is traceable and reviewable rather than invisible.

*A deadline reminder does not fire.* Containment: reminders are generated from a scheduled job with a heartbeat monitor; a missed run raises an operational alert. Deadlines also appear on a daily digest, so silence is itself visible.

*Someone accesses a file they should not have.* Containment: the access is recorded as a distinct audit event, break-glass notifies the responsible partner in real time, and the firm gets a weekly anomalous-access report. The system cannot always prevent it; it can always show it.

*Practice management and the case system disagree.* Containment: nightly reconciliation, divergences named in a report, and practice management wins on client and billing fields by rule.

How we measured. Migration and deadline-integrity checks are run against the firm's own source data and signed off by the firm, item by item. Nothing is sampled and nothing is estimated.

What we are not claiming. We do not claim a time saving, a utilisation improvement or a revenue figure for this scenario. Those depend on how the firm works, not on the software. We also do not claim the system prevents negligence — it reduces the number of places a date can hide.

What we would do differently

We would migrate one practice group, not the firm. On an early rollout we migrated everything at once because the firm wanted a clean cutover date. Two practice groups discovered model gaps in the same week and both were blocked. Phased rollout by practice group is slower, less satisfying, and correct.

We would build the retention engine after the first real destruction request, not before. We built it early, from the policy document, and it was wrong because policy documents describe the ordinary case. The exceptions — holds, reopenings, complaints — are the whole problem, and they only became concrete when a real file needed destroying.

We would spend more of the Blueprint with paralegals and less with partners. Partners describe how matters should run. Paralegals know how they actually run, where the spreadsheets are, and which fields get filled with nonsense because the real information has nowhere to go. The second group produces a better data model.

We would set the conflict-check threshold looser at launch and tighten it with evidence. We launched one build tuned for a manageable review volume, and it was tuned against assumptions rather than the firm's real name distribution. Starting noisy and tightening from data is the safer direction of travel.

What is still running

Reference work in this area continues on the parts that are never finished: better corporate-group resolution for conflict checking, structured extraction from incoming correspondence so evidence checklists update themselves, and matter-type templates for additional immigration categories. Anything touching automated document generation moves slowly and stays behind human review, because a generated document that goes out wrong is the firm's liability, not the software's.

//Results

The numbers

100%
known historical conflicts required to be caught — the tuned recall floor, not precision
16–22 weeks
to first production matters, phased rollout by practice group
20–40
real anonymised matters loaded into the pre-rollout eval set

Verification —This page describes a reference architecture and method, not a named client engagement. We will walk through the matter data model, the authorization design and the audit event schema with an engineer, under NDA, on request. Named client references for legal tech software development can be arranged separately.

//Tech stack
  • Postgres (matters, entities, party roles)
  • Encrypted object store (versioned documents)
  • Authorization service (ethical walls + privilege flags)
  • Event-driven retention engine
  • Append-only audit log

Engagement led by

Prabal Bhandari

Founder & Chief Executive Officer · MS Computer Science, Georgia Tech

//FAQ

Questions, answered straight

No, and we usually advise against it. The case management system sits beside it and integrates. Practice management keeps time, billing and the client record. Replacing billing puts collections at risk to solve a problem that is not about billing.

//Next step

Start with a Blueprint.
Lock the scope. Ship the system.

Contact the studio

Not sure you're ready? Take the Build Readiness Scorecard