A document management system (DMS) is software that stores records in one place while handling versioning, permissions and an access trail. What separates it from a shared folder is not disk space but the fact that three questions finally have a single answer: which version is valid, who is allowed to see this document, and how long must it be kept. Any setup that cannot answer those three is still a file server, whatever it is called.
Where the shared folder breaks down
Most companies start with a network drive or a cloud folder, and that works for a while. The breaking point is not the number of files; it is the moment more than one person starts touching the same document. It shows up in five places:
- The same document multiplying into “final”, “final_v3” and “FINAL”, with nobody sure which one counts.
- Two people opening the same file at once, and one set of edits quietly disappearing.
- A signed contract living only on the personal drive of an employee who has left.
- No record of who opened, downloaded or forwarded a document.
- Contract renewals, guarantee letters and expiry dates sitting in nobody’s calendar.
None of these are storage problems; all of them are process problems. That is why a DMS is a layer of business rules, not a bigger disk. If you want the same logic applied across every internal process, see our guide to internal automation software.
The core modules of a DMS
- Versioning and check-out: a document is locked while edited, saving creates a new version, and old versions are never overwritten.
- Permissions: driven by document type and role, not by folder. Not “the HR folder”, but “only HR specialists can open personnel files”.
- Metadata and full-text search: fields such as document type, counterparty, date and amount are mandatory, and scanned PDFs are unsearchable until they pass through OCR.
- Approval flow: draft to review to approval to publication, recording who approved what, when and with which comment.
- Audit log: views, downloads, shares and deletions stored in a form that cannot be edited afterwards.
- Retention and disposal: a retention period per document type, and a defined action when that period expires.
Disposal is the most frequently skipped module. Under data protection rules, deleting a record once its retention period ends is as much an obligation as keeping it; a “store everything forever” policy creates non-compliance rather than safety.
Search happens in the content, not the file name
Nobody remembers a file name. People remember the client, the date of the contract or a sentence inside it. So two things have to be built together: mandatory metadata fields at upload time, and full-text indexing of the content itself. OCR is compulsory for anything that arrives as a scan, otherwise you accumulate tens of thousands of pages that exist but cannot be found. Make metadata fields pick-lists rather than free text, because “Acme Ltd.”, “Acme Limited” and “acme ltd” are three different counterparties to a search index.
How a version check-in should work
The example below shows the core of saving a new version. Three details matter: without a lock check, concurrent editing silently loses data; creating a new version for identical content inflates the archive for nothing; and retention is calculated from the effective date of the record, not from the day someone uploaded it.
type CheckInResult = { version: number; created: boolean };
async function checkIn(
docId: string,
file: { bytes: Buffer; effectiveDate?: Date },
userId: string,
): Promise<CheckInResult> {
const doc = await repo.lockForUpdate(docId);
// 1) Lock: refuse the write if somebody else is editing.
if (doc.checkedOutBy && doc.checkedOutBy !== userId) {
throw new ConflictError(`Document is checked out by ${doc.checkedOutBy}`);
}
// 2) Identical content should not create a new version.
const hash = sha256(file.bytes);
const latest = await repo.latestVersion(docId);
if (latest && latest.hash === hash) {
await repo.releaseLock(docId, userId);
return { version: latest.version, created: false };
}
// 3) Retention runs from the effective date, not the upload date.
const policy = await repo.retentionPolicy(doc.docType);
const basis = file.effectiveDate ?? doc.effectiveDate ?? new Date();
const retentionUntil = addYears(basis, policy.years);
const version = (latest?.version ?? 0) + 1;
await repo.insertVersion({ docId, version, hash, retentionUntil, userId });
await repo.audit({ docId, version, action: 'CHECK_IN', userId });
await repo.releaseLock(docId, userId);
return { version, created: true };
}Writing the audit entry inside the same transaction is deliberate: logs collected afterwards are always incomplete and useless in an audit. If documents have to travel to other systems such as ERP, accounting or a support desk, move them through a queue with retry-safe handling; the details are in our article on API integration.
Three ways to buy
- Ready-made cloud DMS: fastest start, monthly per-user licence. Fine for standard processes, but industry-specific approval flows and numbering rules rarely bend.
- The document module of your ERP: sensible when the data already lives there, because the file sits next to the account and the order. The limit is everything outside ERP such as HR, legal and quality records — see our ERP guide.
- Custom software: approval flows, document types and integrations built around your company. The right choice when the process really is different or regulation demands a specific audit trail; for the numbers see the cost of custom software.
Five mistakes that break the project
- Migrating the existing archive as-is: folder chaos gets copied into the new system. Define document types and a metadata schema before moving anything.
- Tying permissions to folders: the moment a folder moves, access moves with it. Bind permissions to document type and role instead.
- Demanding too many mandatory fields: an upload screen asking for ten values sends users straight back to email attachments.
- Postponing the retention plan: added later, millions of records have no known effective date and no period can be calculated.
- Leaving the old share open: as long as the shared folder exists, two archives run in parallel. The rollout plan needs a written shutdown date.
How to budget it
A single figure would be misleading, so ask for the quote in five lines: licence or development, migration and OCR of the existing archive, integrations, training and rollout, and annual maintenance. The second line is the one everyone underestimates — classifying and moving a ten-year archive can take longer than building the software. On the compliance side, the principles in our article on a GDPR-compliant website apply equally to documents.
Conclusion
Do not start a document management project with “where shall we put the files”. Start with which version is valid, who may access it and when it must be destroyed. Define document types and metadata before migrating, bind permissions to roles, put retention in the first release, and write down the date you will close the old shared folder. To design this around your own processes, look at our corporate solutions service or request a quote.