In healthcare projects, the requirements for security and traceability are not something you add at the end. They decide the architecture.
An integration project at an ordinary company often starts with two systems that need to talk to each other, and the details get worked out along the way. That is a reasonable way to work when the worst outcome is an incorrect invoice. When the data is health information the calculation changes: the worst outcome is that details about a patient reach someone who should not have them, and that is not a bug you fix in the next sprint.
Settle the legal basis first
Before any technical work begins, it has to be clear who is the data controller, who is the processor, what the legal basis for the processing is, and how long the information may be kept. This is not a formality you can collect later — the answers decide which data you are allowed to fetch, where it may be stored, and what has to be deleted when.
Concretely, the data processing agreement and the risk assessment should be in place, or at least under way with a known direction, before you design the data model. Being told halfway through that national identity numbers cannot be stored in the solution is an architectural change, not a small adjustment.
Fetch as little as possible
Data minimisation is both a legal requirement and good technical practice. Ask specifically: which fields does this feature actually need? Can the patient be identified by an internal key rather than a national identity number? Can you store a calculated answer instead of the raw data it was derived from?
Every column you do not fetch is a column you do not have to secure, audit, delete and account for in a risk assessment. It is the cheapest security work there is.
Build traceability in from the start
The requirement is that it must be possible to answer who has seen which information, and when. That means logging lookups, not just changes — a normal application logging setup often captures the latter and not the former.
The practical consequences: the log must contain the identity of the person who read the data, not just the service account the integration uses. It must be stored so that it cannot be altered afterwards. And it must itself be access-controlled, because it is a record of who has been in contact with the health service — every bit as sensitive as what it protects. Retrofitting this into a running solution is expensive; including it in the first design costs almost nothing.
Access control is a modelling problem
In most systems access is a question of role: a case worker sees cases, a manager sees reports. In healthcare, access is tied to relationship. Does this clinician have a legitimate professional need for information about this patient, right now? The answer changes through the course of a day, and it cannot be expressed with a static list of roles.
The architectural consequence is that the access decision has to be made per lookup, with context, and it has to be justifiable afterwards. That means you cannot filter in the interface and trust it. The filter has to sit as close to the data as possible, so that an API call outside the interface does not bypass it. This is one of the few places where I consistently recommend putting the rule in the database layer as well as in the application, even though it then has to be maintained in two places.
Idempotency and replays
Message-based integrations occasionally deliver the same message twice. The network dropped, the receiver did not acknowledge, the sender retried. In an invoicing system, double processing is annoying. In a patient record it can mean a duplicate in the journal, and that becomes an incident report.
The solution is that every message carries an identifier from the sender, and the receiver remembers which identifiers it has processed:
-- The table that makes replays safe
CREATE TABLE received_message (
message_id uniqueidentifier NOT NULL PRIMARY KEY,
received datetime2 NOT NULL,
result varchar(20) NOT NULL
);
-- On receipt: reject duplicates before processing,
-- in the same transaction as the processing itself.
What matters is that the insert into this table and the processing itself happen in one transaction. Do it in two steps and there is a window in which the message has been processed but not recorded, which puts you back where you started. This is cheap to build in from the start and unpleasant to retrofit into a solution that already has duplicates in production.
Error handling somebody actually sees
An integration that fails silently is worse than one that does not exist, because the organisation starts relying on it. So expect to build three things beyond the data flow itself: a queue for messages that could not be processed, a way to see what is in it, and a way to run them again once the cause has been fixed.
And something that is often forgotten: error messages and queue contents can contain health information. They therefore cannot be sent to an external error-reporting service, cannot sit in a log every developer reads, and cannot go out in an email alert. The alert has to say that message number such-and-such failed with a given error code — not what it contained.
Expect test data to be a project of its own
You will not be allowed to copy production data down into the test environment. That means somebody has to create synthetic patients, synthetic care pathways and synthetic edge cases that are realistic enough to reveal bugs. This is almost always underestimated in the estimate, and it is often what decides whether the integration has actually been tested or merely compiled.
Standards save you work later
The Norwegian health sector has established standards and shared components for message exchange and identity. Using them is slower at the start than defining your own JSON format, and faster in everything that comes after: the next integration, the next vendor, the next audit. Check what the receiving system actually supports, in the version they are running — not what the documentation describes as possible.
Deletion is a feature, not a cleanup
The retention period follows from the legal basis, and it applies to the copies as well: intermediate storage, queues, backups, logs and any reporting databases. If the solution has no mechanism for deleting, you have in practice decided that the retention period is forever, whatever the agreement says.
Practical advice: write down, for each type of data, where it ends up and how long it stays there, before you build. The list will be longer than you expect — the same piece of information often exists in five systems once an integration is running. It is far easier to build deletion into a flow designed for it than to track down the copies afterwards.
The way of working is different
Delivery pace is not set by development alone. It is set by access requests, risk assessments, test environments shared with other projects, and clinicians who have patients to treat and therefore cannot attend a meeting next Tuesday. Plan for that and the project becomes predictable. Plan as if it were an ordinary systems project and you will spend half your time explaining delays.
What this means for the estimate
The sum of the above is that an integration project in healthcare has a substantial share of work that is not functionality: access model, traceability, idempotency, error queue, test data, deletion and documentation. In my experience that share is large enough that an estimate based on the functionality alone will be wrong by a wide margin.
It is not waste, either. These are the same properties that let the solution be audited, handed over to someone else and kept running for ten years. But they have to be in the plan from the beginning, not discovered in week six.