One of the most common misconceptions in software development is the assumption that every application requires a database.
In reality, many internal business solutions do not manage millions of records, complex relationships, transactional workloads, or analytical queries. They typically collect information from users, store it, retrieve it, and occasionally allow searches or updates.
Examples include:
- Event registrations
- Internal campaigns
- Employee check-ins
- Training enrollments
- Surveys
- Feedback platforms
- Department initiatives
- Innovation challenges
For these scenarios, a simpler architecture may provide significant advantages in terms of cost, deployment speed, maintainability, and portability.
The solution described in this article was designed around a core principle:
Use object storage as the persistence layer and store business entities as structured JSON documents.
This approach eliminates the need for a traditional database while preserving the ability to manage records, files, searches, and updates.
The Core Idea
The entire architecture revolves around three components:
The frontend provides the user experience.
The API provides validation and business logic.
The storage layer provides persistence.
The key design decision is that storage becomes the system's database.
Why JSON Instead of SQL
A traditional database introduces several additional components:
For small and medium internal applications, these components often represent more complexity than actual business value.
Instead of storing records inside tables, records can be stored inside a structured JSON document.
Example:
A collection of registrations becomes:
Conceptually, the JSON file becomes the application's database.
Using Object Storage as the Database
Instead of creating tables, a storage container is used.
Example:
The file:
contains all structured records.
The folder:
contains uploaded images.
The application therefore manages only two types of information:
This greatly simplifies the architecture.
Creating a New Record
When a user submits a registration form, the process is intentionally straightforward.
The API performs four operations:
Step 1
Read the current JSON file.
Step 2
Deserialize the JSON structure into memory.
Step 3
Append a new record.
Example:
Step 4
Serialize the updated collection and overwrite the JSON file.
The workflow becomes:
This is effectively the same logical process performed by many database systems but implemented using a single structured file.
Updating Existing Records
Updating follows the same principle.
The API:
- Loads the current JSON.
- Locates the target record.
- Updates the fields.
- Saves the file again.
Example:
Before:
After:
No database transactions are required for small workloads.
Reading and Searching Information
When users perform a search:
the API loads the JSON content and applies filters.
Example:
Matching records are then returned to the frontend.
For moderate datasets, this approach remains highly efficient and significantly simpler than maintaining a database server.
Managing Uploaded Images
Images are intentionally kept separate from business records.
A photo uploaded by the user is saved as an independent object.
Example:
The JSON record stores only the reference.
This provides several benefits:
- smaller JSON files;
- faster loading;
- simpler backup strategy;
- independent file lifecycle management.
Why an API Is Still Necessary
A common question is:
"Why not let the frontend modify the JSON directly?"
The answer is control.
The API performs:
Without an API, every client would need direct write access to storage, introducing significant security and data consistency risks.
The API becomes the only component allowed to modify persistent information.
Benefits of This Approach
The architecture offers several practical advantages.
Low Cost
Only storage and API execution are required.
Rapid Development
Applications can be delivered in days rather than weeks.
Minimal Maintenance
There are no database servers to administer.
Easy Backup
The entire dataset can be backed up simply by copying:
Easy Migration
Moving platforms becomes straightforward because all information already exists in portable formats.
Portability and Self-Hosting
One of the strongest aspects of this architecture is that it remains platform-independent.
The same logical design can run:
In the Cloud
On a Home Server
On a Virtual Machine
Because the application relies on standard concepts rather than platform-specific services, migration becomes relatively simple.
The storage provider may change, but the application logic remains identical.
When This Architecture Makes Sense
This model is particularly effective when:
- the number of records is limited;
- the application is internal;
- development speed is important;
- operational costs should remain low;
- relational data structures are unnecessary.
Typical examples include:
The most important architectural decision in this solution was recognizing that a database was not a business requirement.
The real requirement was persistence.
By using object storage to manage:
and delegating all operations to a lightweight API layer, it was possible to build a solution that remains simple, maintainable, portable, and inexpensive.
Rather than starting with infrastructure, the design starts with the data itself and asks a fundamental question:
"What is the simplest reliable mechanism capable of storing, retrieving, updating, and protecting this information?"
For a large category of internal applications, the answer is often not a database, but a well-structured storage architecture built around JSON documents and object repositories.