Deploy Angular or React apps to Cloudflare Pages using GitHub Actions
I just published a quick guide that walks through deploying a front-end app (Angular or React) to Cloudflare Pages using GitHub Actions for CI/CD.
If you're looking for a simpler alternative to S3 + CloudFront or want to set up blazing-fast, globally distributed static hosting, this might help.
Read the blog here: https://blog.prateekjain.dev/deploy-angular-react-apps-on-cloudflare-pages-9212e91a55d5?sk=b5c890d3632842c6c474b8d4ec7f70ad
https://redd.it/1kovl32
@r_devops
I just published a quick guide that walks through deploying a front-end app (Angular or React) to Cloudflare Pages using GitHub Actions for CI/CD.
If you're looking for a simpler alternative to S3 + CloudFront or want to set up blazing-fast, globally distributed static hosting, this might help.
Read the blog here: https://blog.prateekjain.dev/deploy-angular-react-apps-on-cloudflare-pages-9212e91a55d5?sk=b5c890d3632842c6c474b8d4ec7f70ad
https://redd.it/1kovl32
@r_devops
Medium
Deploy Angular & React Apps to Cloudflare Pages
Deploy your Angular or React app to Cloudflare Pages using GitHub Actions. Learn CI/CD setup, custom domain mapping, and compare with AWS S3 + CloudFront in this step-by-step deployment guide.
Sustainable Development Requires Investing in Quality (Reflection Article)
Hey everyone,
I just shared an article that might resonate with many here. It's about how Lean and XP practices focused on quality — like test automation, trunk-based development, and fast feedback — enable sustainable speed in delivery.
It’s part of a broader series about applying Lean Software Development in the real world, especially across platform and product teams.
Would love to hear how others in DevOps or Platform roles are approaching sustainable speed.
🔗 Quality as the Foundation of Sustainable Development
📚 Full series overview: Lean Software Development in Practice
https://redd.it/1kovc28
@r_devops
Hey everyone,
I just shared an article that might resonate with many here. It's about how Lean and XP practices focused on quality — like test automation, trunk-based development, and fast feedback — enable sustainable speed in delivery.
It’s part of a broader series about applying Lean Software Development in the real world, especially across platform and product teams.
Would love to hear how others in DevOps or Platform roles are approaching sustainable speed.
🔗 Quality as the Foundation of Sustainable Development
📚 Full series overview: Lean Software Development in Practice
https://redd.it/1kovc28
@r_devops
www.eferro.net
Lean Software Development: Quality as the Foundation of Sustainable Development
Third part of the series on quality in Lean Software Development. After exploring how to detect errors early and learn from them, in this en...
What API Management issues do you have?
I am a product manager working on an API Management Solution (API Platform). I want to collect feedback from APIM users about their pain points and frustrations while managing their API lifecycle and working with existing APIMs. I would appreciate any feedback you can give me.
https://redd.it/1kox7bz
@r_devops
I am a product manager working on an API Management Solution (API Platform). I want to collect feedback from APIM users about their pain points and frustrations while managing their API lifecycle and working with existing APIMs. I would appreciate any feedback you can give me.
https://redd.it/1kox7bz
@r_devops
Reddit
From the devops community on Reddit
Explore this post and more from the devops community
Ever hit a point where you’re just... burned out?
Some days, I genuinely love working in cloud—building stuff and learning new services.
Other days, it’s like:
17 tabs open
IAM policies mocking me
Terraform yelling about some tiny diff
And I'm questioning every career choice I've made
It’s wild how something so exciting can also feel so mentally exhausting.
Do you ever hit that wall where your brain says “no more YAML today”?
What do you do to reset when cloud fatigue hits?
https://redd.it/1koysm9
@r_devops
Some days, I genuinely love working in cloud—building stuff and learning new services.
Other days, it’s like:
17 tabs open
IAM policies mocking me
Terraform yelling about some tiny diff
And I'm questioning every career choice I've made
It’s wild how something so exciting can also feel so mentally exhausting.
Do you ever hit that wall where your brain says “no more YAML today”?
What do you do to reset when cloud fatigue hits?
https://redd.it/1koysm9
@r_devops
Reddit
From the devops community on Reddit
Explore this post and more from the devops community
kubectl 1.33 now allows setting up kubectl aliases and default parameters natively
The Kubernetes 1.33 introduces an alpha feature`kuberc`, a feature for managing `kubectl` client-side configurations. This allows for a dedicated file (e.g., `~/.kube/kuberc`) to define user preferences such as aliases and default command flags, distinct from the primary `kubeconfig` file used for cluster authentication.
This can be useful for configurations like:
* Creating aliases, for example, `klogs` for `kubectl logs --follow --tail=50`.
* Ensuring `kubectl apply` defaults to using `--server-side`.
* Setting `kubectl delete` to operate in interactive mode by default.
For those interested in exploring this new functionality, a guide detailing the enabling process and providing configuration examples is available here: [https://cloudfleet.ai/blog/cloud-native-how-to/2025-05-customizing-kubectl-with-kuberc/](https://cloudfleet.ai/blog/cloud-native-how-to/2025-05-customizing-kubectl-with-kuberc/)
What are your initial thoughts on the `kuberc` feature? Which aliases or default overrides would you find most beneficial for your workflows?
https://redd.it/1koxo4a
@r_devops
The Kubernetes 1.33 introduces an alpha feature`kuberc`, a feature for managing `kubectl` client-side configurations. This allows for a dedicated file (e.g., `~/.kube/kuberc`) to define user preferences such as aliases and default command flags, distinct from the primary `kubeconfig` file used for cluster authentication.
This can be useful for configurations like:
* Creating aliases, for example, `klogs` for `kubectl logs --follow --tail=50`.
* Ensuring `kubectl apply` defaults to using `--server-side`.
* Setting `kubectl delete` to operate in interactive mode by default.
For those interested in exploring this new functionality, a guide detailing the enabling process and providing configuration examples is available here: [https://cloudfleet.ai/blog/cloud-native-how-to/2025-05-customizing-kubectl-with-kuberc/](https://cloudfleet.ai/blog/cloud-native-how-to/2025-05-customizing-kubectl-with-kuberc/)
What are your initial thoughts on the `kuberc` feature? Which aliases or default overrides would you find most beneficial for your workflows?
https://redd.it/1koxo4a
@r_devops
Cloudfleet
kuberc is Here! Customizing kubectl with Kubernetes 1.33
Learn about kuberc, the new alpha feature in Kubernetes 1.33 that lets you customize kubectl! Discover how to use ~/.kube/kuberc to create aliases, set default flags, and streamline your Kubernetes workflow.
How hard it will be to find a devops role in EU
Hey! I am working in Cyprus in a reputable company as a DevOps engineer with 3 YEO and several AWS certs. I need to be sponsored by the company to be able to work in the EU as am not an EU passport holder. Is it that hard to find DevOps roles in the EU whether its hybrid or onsite or fully remote?
https://redd.it/1kozteh
@r_devops
Hey! I am working in Cyprus in a reputable company as a DevOps engineer with 3 YEO and several AWS certs. I need to be sponsored by the company to be able to work in the EU as am not an EU passport holder. Is it that hard to find DevOps roles in the EU whether its hybrid or onsite or fully remote?
https://redd.it/1kozteh
@r_devops
Reddit
From the devops community on Reddit
Explore this post and more from the devops community
Gitlab Duo Workflow - Thoughts?
Anyone trying the beta? Seems pretty interesting alternative to other tools out there for an existing Gitlab customer vs paying for Cursor etc. I really like the ability for automation throughout the CI/CD pipeline which is much more value add than just code suggestion.
https://redd.it/1koz6ph
@r_devops
Anyone trying the beta? Seems pretty interesting alternative to other tools out there for an existing Gitlab customer vs paying for Cursor etc. I really like the ability for automation throughout the CI/CD pipeline which is much more value add than just code suggestion.
https://redd.it/1koz6ph
@r_devops
Reddit
From the devops community on Reddit
Explore this post and more from the devops community
What’s the most innovative tasks you have implemented in your job
I would love to hear from your experiences.
For me, one of the most impactful things I did was integrating Atlantis with terraform. We configured it so that changes only get applied after MR approval, which tightened our infra change process.
P.S I know above task might seem straightforward, want to learn from others
https://redd.it/1kp86pq
@r_devops
I would love to hear from your experiences.
For me, one of the most impactful things I did was integrating Atlantis with terraform. We configured it so that changes only get applied after MR approval, which tightened our infra change process.
P.S I know above task might seem straightforward, want to learn from others
https://redd.it/1kp86pq
@r_devops
Reddit
From the devops community on Reddit
Explore this post and more from the devops community
Python Preparation for Devops role
I have an upcoming interview for a product based company (non-maang) for the role of devops.
They are expecting good scripting skills in python. What are the programs i should practice like palindrome, APIs of docker, kubernete, getting api response from servers.
https://redd.it/1kpd07w
@r_devops
I have an upcoming interview for a product based company (non-maang) for the role of devops.
They are expecting good scripting skills in python. What are the programs i should practice like palindrome, APIs of docker, kubernete, getting api response from servers.
https://redd.it/1kpd07w
@r_devops
Reddit
From the devops community on Reddit
Explore this post and more from the devops community
How are you handling lightweight, visual workflow automation for microservice post-deploy tasks?
Hey folks,
I’ve been managing microservice deployments and keep hitting this familiar snag: after a deploy, there’s usually a chain of tasks like restarting services, running smoke tests, sending Slack alerts, or creating tickets if something fails.
Right now, I’m cobbling together bash scripts, GitHub Actions, or Jenkins jobs, but it feels brittle and hard to maintain. I’ve checked out Argo Workflows, Temporal, and n8n — but either they seem too heavy, too complex, or not quite a fit for this kind of “glue logic” between different tools and services.
So, I’m curious — does anyone here have a neat, preferably visual way to create and manage these kinds of internal workflows? Something lightweight, ideally self-hosted, that lets you drag and drop or configure these steps without writing tons of custom code?
Is this a problem others are facing, or is scripting still the easiest way? Would love to hear what approaches work in the wild and if there’s a middle ground I’m missing.
Thanks!
https://redd.it/1kpdptc
@r_devops
Hey folks,
I’ve been managing microservice deployments and keep hitting this familiar snag: after a deploy, there’s usually a chain of tasks like restarting services, running smoke tests, sending Slack alerts, or creating tickets if something fails.
Right now, I’m cobbling together bash scripts, GitHub Actions, or Jenkins jobs, but it feels brittle and hard to maintain. I’ve checked out Argo Workflows, Temporal, and n8n — but either they seem too heavy, too complex, or not quite a fit for this kind of “glue logic” between different tools and services.
So, I’m curious — does anyone here have a neat, preferably visual way to create and manage these kinds of internal workflows? Something lightweight, ideally self-hosted, that lets you drag and drop or configure these steps without writing tons of custom code?
Is this a problem others are facing, or is scripting still the easiest way? Would love to hear what approaches work in the wild and if there’s a middle ground I’m missing.
Thanks!
https://redd.it/1kpdptc
@r_devops
Reddit
From the devops community on Reddit
Explore this post and more from the devops community
Any Salesforce Devops professionals here? What’s your tech stack like?
Also please mention any Salesforce certifications or tool specific certifications you guys have or need !!
https://redd.it/1kpe2gp
@r_devops
Also please mention any Salesforce certifications or tool specific certifications you guys have or need !!
https://redd.it/1kpe2gp
@r_devops
Reddit
From the devops community on Reddit
Explore this post and more from the devops community
Relational vs Document-Oriented Database for Software Architecture
This is the repo with the full examples: https://github.com/LukasNiessen/relational-db-vs-document-store
# Relational vs Document-Oriented Database for Software Architecture
What I go through in here is:
1. Super quick refresher of what these two are
2. Key differences
3. Strengths and weaknesses
4. System design examples (+ Spring Java code)
5. Brief history
In the examples, I choose a relational DB in the first, and a document-oriented DB in the other. The focus is on why did I make that choice. I also provide some example code for both.
In the strengths and weaknesses part, I discuss both what used to be a strength/weakness and how it looks nowadays.
## Super short summary
The two most common types of DBs are:
- Relational database (RDB): PostgreSQL, MySQL, MSSQL, Oracle DB, ...
- Document-oriented database (document store): MongoDB, DynamoDB, CouchDB...
### RDB
The key idea is: fit the data into a big table. The columns are properties and the rows are the values. By doing this, we have our data in a very structured way. So we have much power for querying the data (using SQL). That is, we can do all sorts of filters, joints etc. The way we arrange the data into the table is called the database schema.
#### Example table
A database can have many tables.
### Document stores
The key idea is: just store the data as it is. Suppose we have an object. We just convert it to a JSON and store it as it is. We call this data a document. It's not limited to JSON though, it can also be BSON (binary JSON) or XML for example.
#### Example document
Each document is saved under a unique ID. This ID can be a path, for example in Google Cloud Firestore, but doesn't have to be.
Many documents 'in the same bucket' is called a collection. We can have many collections.
## Differences
#### Schema
- RDBs have a fixed schema. Every row 'has the same schema'.
- Document stores don't have schemas. Each document can 'have a different schema'.
#### Data Structure
- RDBs break data into normalized tables with relationships through foreign keys
- Document stores nest related data directly within documents as embedded objects or arrays
#### Query Language
- RDBs use SQL, a standardized declarative language
- Document stores typically have their own query APIs
- Nowadays, the common document stores support SQL-like queries too
#### Scaling Approach
- RDBs traditionally scale vertically (bigger/better machines)
- Nowadays, the most common RDBs offer horizontal scaling as well (eg. PostgeSQL)
- Document stores are great for horizontal scaling (more machines)
#### Transaction Support
ACID = availability, consistency, isolation, durability
- RDBs have mature ACID transaction support
- Document stores traditionally sacrificed ACID guarantees in favor of performance and availability
- The most common document stores nowadays support ACID though (eg. MongoDB)
## Strengths, weaknesses
### Relational Databases
I want to repeat a few things here again that have changed. As noted, nowadays, most document stores support SQL and ACID. Likewise, most RDBs nowadays support horizontal scaling.
However, let's look at ACID for example. While document stores support it, it's much more mature in RDBs. So if your app puts super high relevance on ACID, then probably RDBs are better. But if your app just needs basic ACID, both works well and this shouldn't be the deciding factor.
For this reason, I have put these points,
This is the repo with the full examples: https://github.com/LukasNiessen/relational-db-vs-document-store
# Relational vs Document-Oriented Database for Software Architecture
What I go through in here is:
1. Super quick refresher of what these two are
2. Key differences
3. Strengths and weaknesses
4. System design examples (+ Spring Java code)
5. Brief history
In the examples, I choose a relational DB in the first, and a document-oriented DB in the other. The focus is on why did I make that choice. I also provide some example code for both.
In the strengths and weaknesses part, I discuss both what used to be a strength/weakness and how it looks nowadays.
## Super short summary
The two most common types of DBs are:
- Relational database (RDB): PostgreSQL, MySQL, MSSQL, Oracle DB, ...
- Document-oriented database (document store): MongoDB, DynamoDB, CouchDB...
### RDB
The key idea is: fit the data into a big table. The columns are properties and the rows are the values. By doing this, we have our data in a very structured way. So we have much power for querying the data (using SQL). That is, we can do all sorts of filters, joints etc. The way we arrange the data into the table is called the database schema.
#### Example table
+----+---------+---------------------+-----+
| ID | Name | Email | Age |
+----+---------+---------------------+-----+
| 1 | Alice | [email protected] | 30 |
| 2 | Bob | [email protected] | 25 |
| 3 | Charlie | [email protected] | 28 |
+----+---------+---------------------+-----+
A database can have many tables.
### Document stores
The key idea is: just store the data as it is. Suppose we have an object. We just convert it to a JSON and store it as it is. We call this data a document. It's not limited to JSON though, it can also be BSON (binary JSON) or XML for example.
#### Example document
{
"user_id": 123,
"name": "Alice",
"email": "[email protected]",
"orders": [
{"id": 1, "item": "Book", "price": 12.99},
{"id": 2, "item": "Pen", "price": 1.50}
]
}
Each document is saved under a unique ID. This ID can be a path, for example in Google Cloud Firestore, but doesn't have to be.
Many documents 'in the same bucket' is called a collection. We can have many collections.
## Differences
#### Schema
- RDBs have a fixed schema. Every row 'has the same schema'.
- Document stores don't have schemas. Each document can 'have a different schema'.
#### Data Structure
- RDBs break data into normalized tables with relationships through foreign keys
- Document stores nest related data directly within documents as embedded objects or arrays
#### Query Language
- RDBs use SQL, a standardized declarative language
- Document stores typically have their own query APIs
- Nowadays, the common document stores support SQL-like queries too
#### Scaling Approach
- RDBs traditionally scale vertically (bigger/better machines)
- Nowadays, the most common RDBs offer horizontal scaling as well (eg. PostgeSQL)
- Document stores are great for horizontal scaling (more machines)
#### Transaction Support
ACID = availability, consistency, isolation, durability
- RDBs have mature ACID transaction support
- Document stores traditionally sacrificed ACID guarantees in favor of performance and availability
- The most common document stores nowadays support ACID though (eg. MongoDB)
## Strengths, weaknesses
### Relational Databases
I want to repeat a few things here again that have changed. As noted, nowadays, most document stores support SQL and ACID. Likewise, most RDBs nowadays support horizontal scaling.
However, let's look at ACID for example. While document stores support it, it's much more mature in RDBs. So if your app puts super high relevance on ACID, then probably RDBs are better. But if your app just needs basic ACID, both works well and this shouldn't be the deciding factor.
For this reason, I have put these points,
GitHub
GitHub - LukasNiessen/relational-db-vs-document-store
Contribute to LukasNiessen/relational-db-vs-document-store development by creating an account on GitHub.
that are supported in both, in parentheses.
Strengths:
- Data Integrity: Strong schema enforcement ensures data consistency
- (Complex Querying: Great for complex joins and aggregations across multiple tables)
- (ACID)
Weaknesses:
- Schema: While the schema was listed as a strength, it also is a weakness. Changing the schema requires migrations which can be painful
- Object-Relational Impedance Mismatch: Translating between application objects and relational tables adds complexity. Hibernate and other Object-relational mapping (ORM) frameworks help though.
- (Horizontal Scaling: Supported but sharding is more complex as compared to document stores)
- Initial Dev Speed: Setting up schemas etc takes some time
### Document-Oriented Databases
Strengths:
- Schema Flexibility: Better for heterogeneous data structures
- Throughput: Supports high throughput, especially write throughput
- (Horizontal Scaling: Horizontal scaling is easier, you can shard document-wise (document 1-1000 on computer A and 1000-2000 on computer B))
- Performance for Document-Based Access: Retrieving or updating an entire document is very efficient
- One-to-Many Relationships: Superior in this regard. You don't need joins or other operations.
- Locality: See below
- Initial Dev Speed: Getting started is quicker due to the flexibility
Weaknesses:
- Complex Relationships: Many-to-one and many-to-many relationships are difficult and often require denormalization or application-level joins
- Data Consistency: More responsibility falls on application code to maintain data integrity
- Query Optimization: Less mature optimization engines compared to relational systems
- Storage Efficiency: Potential data duplication increases storage requirements
- Locality: See below
### Locality
I have listed locality as a strength and a weakness of document stores. Here is what I mean with this.
In document stores, cocuments are typically stored as a single, continuous string, encoded in formats like JSON, XML, or binary variants such as MongoDB's BSON. This structure provides a locality advantage when applications need to access entire documents. Storing related data together minimizes disk seeks, unlike relational databases (RDBs) where data split across multiple tables - this requires multiple index lookups, increasing retrieval time.
However, it's only a benefit when we need (almost) the entire document at once. Document stores typically load the entire document, even if only a small part is accessed. This is inefficient for large documents. Similarly, updates often require rewriting the entire document. So to keep these downsides small, make sure your documents are small.
Last note: Locality isn't exclusive to document stores. For example Google Spanner or Oracle achieve a similar locality in a relational model.
## System Design Examples
Note that I limit the examples to the minimum so the article is not totally bloated. The code is incomplete on purpose. You can find the complete code in the examples folder of the repo.
The examples folder contains two complete applications:
1.
2.
Each example has its own README file with instructions for running the applications.
## Example 1: Financial Transaction System
### Requirements
#### Functional requirements
- Process payments and transfers
- Maintain accurate account balances
- Store audit trails for all operations
#### Non-functional requirements
- Reliability (!!)
- Data consistency (!!)
#### Why Relational is Better Here
We want reliability and data consistency. Though document stores support this too (ACID for example), they are less mature in this regard. The benefits of document stores are not interesting for us, so we go with an RDB.
Note: If we would expand this example and add things
Strengths:
- Data Integrity: Strong schema enforcement ensures data consistency
- (Complex Querying: Great for complex joins and aggregations across multiple tables)
- (ACID)
Weaknesses:
- Schema: While the schema was listed as a strength, it also is a weakness. Changing the schema requires migrations which can be painful
- Object-Relational Impedance Mismatch: Translating between application objects and relational tables adds complexity. Hibernate and other Object-relational mapping (ORM) frameworks help though.
- (Horizontal Scaling: Supported but sharding is more complex as compared to document stores)
- Initial Dev Speed: Setting up schemas etc takes some time
### Document-Oriented Databases
Strengths:
- Schema Flexibility: Better for heterogeneous data structures
- Throughput: Supports high throughput, especially write throughput
- (Horizontal Scaling: Horizontal scaling is easier, you can shard document-wise (document 1-1000 on computer A and 1000-2000 on computer B))
- Performance for Document-Based Access: Retrieving or updating an entire document is very efficient
- One-to-Many Relationships: Superior in this regard. You don't need joins or other operations.
- Locality: See below
- Initial Dev Speed: Getting started is quicker due to the flexibility
Weaknesses:
- Complex Relationships: Many-to-one and many-to-many relationships are difficult and often require denormalization or application-level joins
- Data Consistency: More responsibility falls on application code to maintain data integrity
- Query Optimization: Less mature optimization engines compared to relational systems
- Storage Efficiency: Potential data duplication increases storage requirements
- Locality: See below
### Locality
I have listed locality as a strength and a weakness of document stores. Here is what I mean with this.
In document stores, cocuments are typically stored as a single, continuous string, encoded in formats like JSON, XML, or binary variants such as MongoDB's BSON. This structure provides a locality advantage when applications need to access entire documents. Storing related data together minimizes disk seeks, unlike relational databases (RDBs) where data split across multiple tables - this requires multiple index lookups, increasing retrieval time.
However, it's only a benefit when we need (almost) the entire document at once. Document stores typically load the entire document, even if only a small part is accessed. This is inefficient for large documents. Similarly, updates often require rewriting the entire document. So to keep these downsides small, make sure your documents are small.
Last note: Locality isn't exclusive to document stores. For example Google Spanner or Oracle achieve a similar locality in a relational model.
## System Design Examples
Note that I limit the examples to the minimum so the article is not totally bloated. The code is incomplete on purpose. You can find the complete code in the examples folder of the repo.
The examples folder contains two complete applications:
1.
financial-transaction-system - A Spring Boot and React application using a relational database (H2)2.
content-management-system - A Spring Boot and React application using a document-oriented database (MongoDB)Each example has its own README file with instructions for running the applications.
## Example 1: Financial Transaction System
### Requirements
#### Functional requirements
- Process payments and transfers
- Maintain accurate account balances
- Store audit trails for all operations
#### Non-functional requirements
- Reliability (!!)
- Data consistency (!!)
#### Why Relational is Better Here
We want reliability and data consistency. Though document stores support this too (ACID for example), they are less mature in this regard. The benefits of document stores are not interesting for us, so we go with an RDB.
Note: If we would expand this example and add things
like profiles of sellers, ratings and more, we might want to add a separate DB where we have different priorities such as availability and high throughput. With two separate DBs we can support different requirements and scale them independently.
### Data Model
### Spring Boot Implementation
## System Design Example 2: Content Management System
A content management system.
### Requirements
- Store various
### Data Model
Accounts:
- account_id (PK = Primary Key)
- customer_id (FK = Foreign Key)
- account_type
- balance
- created_at
- status
Transactions:
- transaction_id (PK)
- from_account_id (FK)
- to_account_id (FK)
- amount
- type
- status
- created_at
- reference_number
### Spring Boot Implementation
// Entity classes
@Entity
@Table(name = "accounts")
public class Account {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long accountId;
@Column(nullable = false)
private Long customerId;
@Column(nullable = false)
private String accountType;
@Column(nullable = false)
private BigDecimal balance;
@Column(nullable = false)
private LocalDateTime createdAt;
@Column(nullable = false)
private String status;
// Getters and setters
}
@Entity
@Table(name = "transactions")
public class Transaction {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long transactionId;
@ManyToOne
@JoinColumn(name = "from_account_id")
private Account fromAccount;
@ManyToOne
@JoinColumn(name = "to_account_id")
private Account toAccount;
@Column(nullable = false)
private BigDecimal amount;
@Column(nullable = false)
private String type;
@Column(nullable = false)
private String status;
@Column(nullable = false)
private LocalDateTime createdAt;
@Column(nullable = false)
private String referenceNumber;
// Getters and setters
}
// Repository
public interface TransactionRepository extends JpaRepository<Transaction, Long> {
List<Transaction> findByFromAccountAccountIdOrToAccountAccountId(Long accountId, Long sameAccountId);
List<Transaction> findByCreatedAtBetween(LocalDateTime start, LocalDateTime end);
}
// Service with transaction support
@Service
public class TransferService {
private final AccountRepository accountRepository;
private final TransactionRepository transactionRepository;
@Autowired
public TransferService(AccountRepository accountRepository, TransactionRepository transactionRepository) {
this.accountRepository = accountRepository;
this.transactionRepository = transactionRepository;
}
@Transactional
public Transaction transferFunds(Long fromAccountId, Long toAccountId, BigDecimal amount) {
Account fromAccount = accountRepository.findById(fromAccountId)
.orElseThrow(() -> new AccountNotFoundException("Source account not found"));
Account toAccount = accountRepository.findById(toAccountId)
.orElseThrow(() -> new AccountNotFoundException("Destination account not found"));
if (fromAccount.getBalance().compareTo(amount) < 0) {
throw new InsufficientFundsException("Insufficient funds in source account");
}
// Update balances
fromAccount.setBalance(fromAccount.getBalance().subtract(amount));
toAccount.setBalance(toAccount.getBalance().add(amount));
accountRepository.save(fromAccount);
accountRepository.save(toAccount);
// Create transaction record
Transaction transaction = new Transaction();
transaction.setFromAccount(fromAccount);
transaction.setToAccount(toAccount);
transaction.setAmount(amount);
transaction.setType("TRANSFER");
transaction.setStatus("COMPLETED");
transaction.setCreatedAt(LocalDateTime.now());
transaction.setReferenceNumber(generateReferenceNumber());
return transactionRepository.save(transaction);
}
private String generateReferenceNumber() {
return "TXN" + System.currentTimeMillis();
}
}
## System Design Example 2: Content Management System
A content management system.
### Requirements
- Store various
Relational vs Document-Oriented Database for Software Architecture
This is the repo with the full examples: https://github.com/LukasNiessen/relational-db-vs-document-store
# Relational vs Document-Oriented Database for Software Architecture
What I go through in here is:
1. Super quick refresher of what these two are
2. Key differences
3. Strengths and weaknesses
4. System design examples (+ Spring Java code)
5. Brief history
In the examples, I choose a relational DB in the first, and a document-oriented DB in the other. The focus is on _why_ did I make that choice. I also provide some example code for both.
In the strengths and weaknesses part, I discuss both what _used to be a strength/weakness_ and how it looks nowadays.
## Super short summary
The two most common types of DBs are:
- **Relational database (RDB)**: PostgreSQL, MySQL, MSSQL, Oracle DB, ...
- **Document-oriented database (document store):** MongoDB, DynamoDB, CouchDB...
### RDB
The key idea is: **fit the data into a big table**. The columns are _properties_ and the rows are the _values_. By doing this, we have our data in a very structured way. So we have much power for querying the data (using SQL). That is, we can do all sorts of filters, joints etc. The _way_ we arrange the data into the table is called the _database schema_.
#### Example table
```
+----+---------+---------------------+-----+
| ID | Name | Email | Age |
+----+---------+---------------------+-----+
| 1 | Alice | [email protected] | 30 |
| 2 | Bob | [email protected] | 25 |
| 3 | Charlie | [email protected] | 28 |
+----+---------+---------------------+-----+
```
A database can have many tables.
### Document stores
The key idea is: **just store the data as it is**. Suppose we have an object. We just convert it to a JSON and store it as it is. We call this data a _document_. It's not limited to JSON though, it can also be BSON (binary JSON) or XML for example.
#### Example document
```JSON
{
"user_id": 123,
"name": "Alice",
"email": "[email protected]",
"orders": [
{"id": 1, "item": "Book", "price": 12.99},
{"id": 2, "item": "Pen", "price": 1.50}
]
}
```
Each document is saved under a unique ID. This ID can be a path, for example in Google Cloud Firestore, but doesn't have to be.
Many documents _'in the same bucket'_ is called a _collection_. We can have many collections.
## Differences
#### Schema
- RDBs have a fixed schema. Every row _'has the same schema'_.
- Document stores don't have schemas. Each document can _'have a different schema'_.
#### Data Structure
- RDBs break data into normalized tables with relationships through foreign keys
- Document stores nest related data directly within documents as embedded objects or arrays
#### Query Language
- RDBs use SQL, a standardized declarative language
- Document stores typically have their own query APIs
- Nowadays, the common document stores support SQL-like queries too
#### Scaling Approach
- RDBs traditionally scale vertically (bigger/better machines)
- Nowadays, the most common RDBs offer horizontal scaling as well (eg. PostgeSQL)
- Document stores are great for horizontal scaling (more machines)
#### Transaction Support
ACID = availability, consistency, isolation, durability
- RDBs have mature ACID transaction support
- Document stores traditionally sacrificed ACID guarantees in favor of performance and availability
- The most common document stores nowadays support ACID though (eg. MongoDB)
## Strengths, weaknesses
### Relational Databases
I want to repeat a few things here again that have changed. As noted, nowadays, most document stores support SQL and ACID. Likewise, most RDBs nowadays support horizontal scaling.
However, let's look at ACID for example. While document stores support it, it's much more mature in RDBs. So if your app puts super high relevance on ACID, then probably RDBs are better. But if your app just needs basic ACID, both works well and this shouldn't be the deciding factor.
For this reason, I have put these points,
This is the repo with the full examples: https://github.com/LukasNiessen/relational-db-vs-document-store
# Relational vs Document-Oriented Database for Software Architecture
What I go through in here is:
1. Super quick refresher of what these two are
2. Key differences
3. Strengths and weaknesses
4. System design examples (+ Spring Java code)
5. Brief history
In the examples, I choose a relational DB in the first, and a document-oriented DB in the other. The focus is on _why_ did I make that choice. I also provide some example code for both.
In the strengths and weaknesses part, I discuss both what _used to be a strength/weakness_ and how it looks nowadays.
## Super short summary
The two most common types of DBs are:
- **Relational database (RDB)**: PostgreSQL, MySQL, MSSQL, Oracle DB, ...
- **Document-oriented database (document store):** MongoDB, DynamoDB, CouchDB...
### RDB
The key idea is: **fit the data into a big table**. The columns are _properties_ and the rows are the _values_. By doing this, we have our data in a very structured way. So we have much power for querying the data (using SQL). That is, we can do all sorts of filters, joints etc. The _way_ we arrange the data into the table is called the _database schema_.
#### Example table
```
+----+---------+---------------------+-----+
| ID | Name | Email | Age |
+----+---------+---------------------+-----+
| 1 | Alice | [email protected] | 30 |
| 2 | Bob | [email protected] | 25 |
| 3 | Charlie | [email protected] | 28 |
+----+---------+---------------------+-----+
```
A database can have many tables.
### Document stores
The key idea is: **just store the data as it is**. Suppose we have an object. We just convert it to a JSON and store it as it is. We call this data a _document_. It's not limited to JSON though, it can also be BSON (binary JSON) or XML for example.
#### Example document
```JSON
{
"user_id": 123,
"name": "Alice",
"email": "[email protected]",
"orders": [
{"id": 1, "item": "Book", "price": 12.99},
{"id": 2, "item": "Pen", "price": 1.50}
]
}
```
Each document is saved under a unique ID. This ID can be a path, for example in Google Cloud Firestore, but doesn't have to be.
Many documents _'in the same bucket'_ is called a _collection_. We can have many collections.
## Differences
#### Schema
- RDBs have a fixed schema. Every row _'has the same schema'_.
- Document stores don't have schemas. Each document can _'have a different schema'_.
#### Data Structure
- RDBs break data into normalized tables with relationships through foreign keys
- Document stores nest related data directly within documents as embedded objects or arrays
#### Query Language
- RDBs use SQL, a standardized declarative language
- Document stores typically have their own query APIs
- Nowadays, the common document stores support SQL-like queries too
#### Scaling Approach
- RDBs traditionally scale vertically (bigger/better machines)
- Nowadays, the most common RDBs offer horizontal scaling as well (eg. PostgeSQL)
- Document stores are great for horizontal scaling (more machines)
#### Transaction Support
ACID = availability, consistency, isolation, durability
- RDBs have mature ACID transaction support
- Document stores traditionally sacrificed ACID guarantees in favor of performance and availability
- The most common document stores nowadays support ACID though (eg. MongoDB)
## Strengths, weaknesses
### Relational Databases
I want to repeat a few things here again that have changed. As noted, nowadays, most document stores support SQL and ACID. Likewise, most RDBs nowadays support horizontal scaling.
However, let's look at ACID for example. While document stores support it, it's much more mature in RDBs. So if your app puts super high relevance on ACID, then probably RDBs are better. But if your app just needs basic ACID, both works well and this shouldn't be the deciding factor.
For this reason, I have put these points,
GitHub
GitHub - LukasNiessen/relational-db-vs-document-store
Contribute to LukasNiessen/relational-db-vs-document-store development by creating an account on GitHub.
that are supported in both, in **parentheses**.
**Strengths:**
- **Data Integrity**: Strong schema enforcement ensures data consistency
- (**Complex Querying**: Great for complex joins and aggregations across multiple tables)
- (**ACID**)
**Weaknesses:**
- **Schema**: While the schema was listed as a strength, it also is a weakness. Changing the schema requires migrations which can be painful
- **Object-Relational Impedance Mismatch**: Translating between application objects and relational tables adds complexity. Hibernate and other Object-relational mapping (ORM) frameworks help though.
- (**Horizontal Scaling**: Supported but sharding is more complex as compared to document stores)
- **Initial Dev Speed**: Setting up schemas etc takes some time
### Document-Oriented Databases
**Strengths:**
- **Schema Flexibility**: Better for heterogeneous data structures
- **Throughput:** Supports high throughput, especially write throughput
- (**Horizontal Scaling**: Horizontal scaling is easier, you can shard document-wise (document 1-1000 on computer A and 1000-2000 on computer B))
- **Performance for Document-Based Access**: Retrieving or updating an entire document is very efficient
- **One-to-Many Relationships**: Superior in this regard. You don't need joins or other operations.
- **Locality**: See below
- **Initial Dev Speed**: Getting started is quicker due to the flexibility
**Weaknesses:**
- **Complex Relationships**: Many-to-one and many-to-many relationships are difficult and often require denormalization or application-level joins
- **Data Consistency**: More responsibility falls on application code to maintain data integrity
- **Query Optimization**: Less mature optimization engines compared to relational systems
- **Storage Efficiency**: Potential data duplication increases storage requirements
- **Locality**: See below
### Locality
I have listed locality as a strength and a weakness of document stores. Here is what I mean with this.
In document stores, cocuments are typically stored as a single, continuous string, encoded in formats like JSON, XML, or binary variants such as MongoDB's BSON. This structure provides a locality advantage when applications need to access entire documents. Storing related data together minimizes disk seeks, unlike relational databases (RDBs) where data split across multiple tables - this requires multiple index lookups, increasing retrieval time.
However, it's only a benefit when we need (almost) the entire document at once. Document stores typically load the entire document, even if only a small part is accessed. This is inefficient for large documents. Similarly, updates often require rewriting the entire document. So to keep these downsides small, make sure your documents are small.
Last note: Locality isn't exclusive to document stores. For example Google Spanner or Oracle achieve a similar locality in a relational model.
## System Design Examples
Note that I limit the examples to the minimum so the article is not totally bloated. The code is incomplete on purpose. You can find the complete code in the examples folder of the repo.
The examples folder contains two complete applications:
1. `financial-transaction-system` - A Spring Boot and React application using a relational database (H2)
2. `content-management-system` - A Spring Boot and React application using a document-oriented database (MongoDB)
Each example has its own README file with instructions for running the applications.
## Example 1: Financial Transaction System
### Requirements
#### Functional requirements
- Process payments and transfers
- Maintain accurate account balances
- Store audit trails for all operations
#### Non-functional requirements
- Reliability (!!)
- Data consistency (!!)
#### Why Relational is Better Here
We want reliability and data consistency. Though document stores support this too (ACID for example), they are less mature in this regard. The benefits of document stores are not interesting for us, so we go with an RDB.
Note: If we would expand this example and add things
**Strengths:**
- **Data Integrity**: Strong schema enforcement ensures data consistency
- (**Complex Querying**: Great for complex joins and aggregations across multiple tables)
- (**ACID**)
**Weaknesses:**
- **Schema**: While the schema was listed as a strength, it also is a weakness. Changing the schema requires migrations which can be painful
- **Object-Relational Impedance Mismatch**: Translating between application objects and relational tables adds complexity. Hibernate and other Object-relational mapping (ORM) frameworks help though.
- (**Horizontal Scaling**: Supported but sharding is more complex as compared to document stores)
- **Initial Dev Speed**: Setting up schemas etc takes some time
### Document-Oriented Databases
**Strengths:**
- **Schema Flexibility**: Better for heterogeneous data structures
- **Throughput:** Supports high throughput, especially write throughput
- (**Horizontal Scaling**: Horizontal scaling is easier, you can shard document-wise (document 1-1000 on computer A and 1000-2000 on computer B))
- **Performance for Document-Based Access**: Retrieving or updating an entire document is very efficient
- **One-to-Many Relationships**: Superior in this regard. You don't need joins or other operations.
- **Locality**: See below
- **Initial Dev Speed**: Getting started is quicker due to the flexibility
**Weaknesses:**
- **Complex Relationships**: Many-to-one and many-to-many relationships are difficult and often require denormalization or application-level joins
- **Data Consistency**: More responsibility falls on application code to maintain data integrity
- **Query Optimization**: Less mature optimization engines compared to relational systems
- **Storage Efficiency**: Potential data duplication increases storage requirements
- **Locality**: See below
### Locality
I have listed locality as a strength and a weakness of document stores. Here is what I mean with this.
In document stores, cocuments are typically stored as a single, continuous string, encoded in formats like JSON, XML, or binary variants such as MongoDB's BSON. This structure provides a locality advantage when applications need to access entire documents. Storing related data together minimizes disk seeks, unlike relational databases (RDBs) where data split across multiple tables - this requires multiple index lookups, increasing retrieval time.
However, it's only a benefit when we need (almost) the entire document at once. Document stores typically load the entire document, even if only a small part is accessed. This is inefficient for large documents. Similarly, updates often require rewriting the entire document. So to keep these downsides small, make sure your documents are small.
Last note: Locality isn't exclusive to document stores. For example Google Spanner or Oracle achieve a similar locality in a relational model.
## System Design Examples
Note that I limit the examples to the minimum so the article is not totally bloated. The code is incomplete on purpose. You can find the complete code in the examples folder of the repo.
The examples folder contains two complete applications:
1. `financial-transaction-system` - A Spring Boot and React application using a relational database (H2)
2. `content-management-system` - A Spring Boot and React application using a document-oriented database (MongoDB)
Each example has its own README file with instructions for running the applications.
## Example 1: Financial Transaction System
### Requirements
#### Functional requirements
- Process payments and transfers
- Maintain accurate account balances
- Store audit trails for all operations
#### Non-functional requirements
- Reliability (!!)
- Data consistency (!!)
#### Why Relational is Better Here
We want reliability and data consistency. Though document stores support this too (ACID for example), they are less mature in this regard. The benefits of document stores are not interesting for us, so we go with an RDB.
Note: If we would expand this example and add things
like _profiles of sellers_, _ratings_ and more, we might want to add a separate DB where we have different priorities such as availability and high throughput. With two separate DBs we can support different requirements and scale them independently.
### Data Model
```
Accounts:
- account_id (PK = Primary Key)
- customer_id (FK = Foreign Key)
- account_type
- balance
- created_at
- status
Transactions:
- transaction_id (PK)
- from_account_id (FK)
- to_account_id (FK)
- amount
- type
- status
- created_at
- reference_number
```
### Spring Boot Implementation
```java
// Entity classes
@Entity
@Table(name = "accounts")
public class Account {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long accountId;
@Column(nullable = false)
private Long customerId;
@Column(nullable = false)
private String accountType;
@Column(nullable = false)
private BigDecimal balance;
@Column(nullable = false)
private LocalDateTime createdAt;
@Column(nullable = false)
private String status;
// Getters and setters
}
@Entity
@Table(name = "transactions")
public class Transaction {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long transactionId;
@ManyToOne
@JoinColumn(name = "from_account_id")
private Account fromAccount;
@ManyToOne
@JoinColumn(name = "to_account_id")
private Account toAccount;
@Column(nullable = false)
private BigDecimal amount;
@Column(nullable = false)
private String type;
@Column(nullable = false)
private String status;
@Column(nullable = false)
private LocalDateTime createdAt;
@Column(nullable = false)
private String referenceNumber;
// Getters and setters
}
// Repository
public interface TransactionRepository extends JpaRepository<Transaction, Long> {
List<Transaction> findByFromAccountAccountIdOrToAccountAccountId(Long accountId, Long sameAccountId);
List<Transaction> findByCreatedAtBetween(LocalDateTime start, LocalDateTime end);
}
// Service with transaction support
@Service
public class TransferService {
private final AccountRepository accountRepository;
private final TransactionRepository transactionRepository;
@Autowired
public TransferService(AccountRepository accountRepository, TransactionRepository transactionRepository) {
this.accountRepository = accountRepository;
this.transactionRepository = transactionRepository;
}
@Transactional
public Transaction transferFunds(Long fromAccountId, Long toAccountId, BigDecimal amount) {
Account fromAccount = accountRepository.findById(fromAccountId)
.orElseThrow(() -> new AccountNotFoundException("Source account not found"));
Account toAccount = accountRepository.findById(toAccountId)
.orElseThrow(() -> new AccountNotFoundException("Destination account not found"));
if (fromAccount.getBalance().compareTo(amount) < 0) {
throw new InsufficientFundsException("Insufficient funds in source account");
}
// Update balances
fromAccount.setBalance(fromAccount.getBalance().subtract(amount));
toAccount.setBalance(toAccount.getBalance().add(amount));
accountRepository.save(fromAccount);
accountRepository.save(toAccount);
// Create transaction record
Transaction transaction = new Transaction();
transaction.setFromAccount(fromAccount);
transaction.setToAccount(toAccount);
transaction.setAmount(amount);
transaction.setType("TRANSFER");
transaction.setStatus("COMPLETED");
transaction.setCreatedAt(LocalDateTime.now());
transaction.setReferenceNumber(generateReferenceNumber());
return transactionRepository.save(transaction);
}
private String generateReferenceNumber() {
return "TXN" + System.currentTimeMillis();
}
}
```
## System Design Example 2: Content Management System
A content management system.
### Requirements
- Store various
### Data Model
```
Accounts:
- account_id (PK = Primary Key)
- customer_id (FK = Foreign Key)
- account_type
- balance
- created_at
- status
Transactions:
- transaction_id (PK)
- from_account_id (FK)
- to_account_id (FK)
- amount
- type
- status
- created_at
- reference_number
```
### Spring Boot Implementation
```java
// Entity classes
@Entity
@Table(name = "accounts")
public class Account {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long accountId;
@Column(nullable = false)
private Long customerId;
@Column(nullable = false)
private String accountType;
@Column(nullable = false)
private BigDecimal balance;
@Column(nullable = false)
private LocalDateTime createdAt;
@Column(nullable = false)
private String status;
// Getters and setters
}
@Entity
@Table(name = "transactions")
public class Transaction {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long transactionId;
@ManyToOne
@JoinColumn(name = "from_account_id")
private Account fromAccount;
@ManyToOne
@JoinColumn(name = "to_account_id")
private Account toAccount;
@Column(nullable = false)
private BigDecimal amount;
@Column(nullable = false)
private String type;
@Column(nullable = false)
private String status;
@Column(nullable = false)
private LocalDateTime createdAt;
@Column(nullable = false)
private String referenceNumber;
// Getters and setters
}
// Repository
public interface TransactionRepository extends JpaRepository<Transaction, Long> {
List<Transaction> findByFromAccountAccountIdOrToAccountAccountId(Long accountId, Long sameAccountId);
List<Transaction> findByCreatedAtBetween(LocalDateTime start, LocalDateTime end);
}
// Service with transaction support
@Service
public class TransferService {
private final AccountRepository accountRepository;
private final TransactionRepository transactionRepository;
@Autowired
public TransferService(AccountRepository accountRepository, TransactionRepository transactionRepository) {
this.accountRepository = accountRepository;
this.transactionRepository = transactionRepository;
}
@Transactional
public Transaction transferFunds(Long fromAccountId, Long toAccountId, BigDecimal amount) {
Account fromAccount = accountRepository.findById(fromAccountId)
.orElseThrow(() -> new AccountNotFoundException("Source account not found"));
Account toAccount = accountRepository.findById(toAccountId)
.orElseThrow(() -> new AccountNotFoundException("Destination account not found"));
if (fromAccount.getBalance().compareTo(amount) < 0) {
throw new InsufficientFundsException("Insufficient funds in source account");
}
// Update balances
fromAccount.setBalance(fromAccount.getBalance().subtract(amount));
toAccount.setBalance(toAccount.getBalance().add(amount));
accountRepository.save(fromAccount);
accountRepository.save(toAccount);
// Create transaction record
Transaction transaction = new Transaction();
transaction.setFromAccount(fromAccount);
transaction.setToAccount(toAccount);
transaction.setAmount(amount);
transaction.setType("TRANSFER");
transaction.setStatus("COMPLETED");
transaction.setCreatedAt(LocalDateTime.now());
transaction.setReferenceNumber(generateReferenceNumber());
return transactionRepository.save(transaction);
}
private String generateReferenceNumber() {
return "TXN" + System.currentTimeMillis();
}
}
```
## System Design Example 2: Content Management System
A content management system.
### Requirements
- Store various
content types, including articles and products
- Allow adding new content types
- Support comments
### Non-functional requirements
- Performance
- Availability
- Elasticity
### Why Document Store is Better Here
As we have no critical transaction like in the previous example but are only interested in performance, availability and elasticity, document stores are a great choice. Considering that various content types is a requirement, our life is easier with document stores as they are schema-less.
### Data Model
```json
// Article document
{
"id": "article123",
"type": "article",
"title": "Understanding NoSQL",
"author": {
"id": "user456",
"name": "Jane Smith",
"email": "[email protected]"
},
"content": "Lorem ipsum dolor sit amet...",
"tags": ["database", "nosql", "tutorial"],
"published": true,
"publishedDate": "2025-05-01T10:30:00Z",
"comments": [
{
"id": "comment789",
"userId": "user101",
"userName": "Bob Johnson",
"text": "Great article!",
"timestamp": "2025-05-02T14:20:00Z",
"replies": [
{
"id": "reply456",
"userId": "user456",
"userName": "Jane Smith",
"text": "Thanks Bob!",
"timestamp": "2025-05-02T15:45:00Z"
}
]
}
],
"metadata": {
"viewCount": 1250,
"likeCount": 42,
"featuredImage": "/images/nosql-header.jpg",
"estimatedReadTime": 8
}
}
// Product document (completely different structure)
{
"id": "product789",
"type": "product",
"name": "Premium Ergonomic Chair",
"price": 299.99,
"categories": ["furniture", "office", "ergonomic"],
"variants": [
{
"color": "black",
"sku": "EC-BLK-001",
"inStock": 23
},
{
"color": "gray",
"sku": "EC-GRY-001",
"inStock": 14
}
],
"specifications": {
"weight": "15kg",
"dimensions": "65x70x120cm",
"material": "Mesh and aluminum"
}
}
```
### Spring Boot Implementation with MongoDB
```java
@Document(collection = "content")
public class ContentItem {
@Id
private String id;
private String type;
private Map<String, Object> data;
// Common fields can be explicit
private boolean published;
private Date createdAt;
private Date updatedAt;
// The rest can be dynamic
@DBRef(lazy = true)
private User author;
private List<Comment> comments;
// Basic getters and setters
}
// MongoDB Repository
public interface ContentRepository extends MongoRepository<ContentItem, String> {
List<ContentItem> findByType(String type);
List<ContentItem> findByTypeAndPublishedTrue(String type);
List<ContentItem> findByData_TagsContaining(String tag);
}
// Service for content management
@Service
public class ContentService {
private final ContentRepository contentRepository;
@Autowired
public ContentService(ContentRepository contentRepository) {
this.contentRepository = contentRepository;
}
public ContentItem createContent(String type, Map<String, Object> data, User author) {
ContentItem content = new ContentItem();
content.setType(type);
content.setData(data);
content.setAuthor(author);
content.setCreatedAt(new Date());
content.setUpdatedAt(new Date());
content.setPublished(false);
return contentRepository.save(content);
}
public ContentItem addComment(String contentId, Comment comment) {
ContentItem content = contentRepository.findById(contentId)
.orElseThrow(() -> new ContentNotFoundException("Content not found"));
if (content.getComments() == null) {
content.setComments(new ArrayList<>());
}
content.getComments().add(comment);
content.setUpdatedAt(new Date());
return contentRepository.save(content);
}
// Easily add new fields without migrations
public ContentItem addMetadata(String contentId, String key, Object value) {
ContentItem content = contentRepository.findById(contentId)
- Allow adding new content types
- Support comments
### Non-functional requirements
- Performance
- Availability
- Elasticity
### Why Document Store is Better Here
As we have no critical transaction like in the previous example but are only interested in performance, availability and elasticity, document stores are a great choice. Considering that various content types is a requirement, our life is easier with document stores as they are schema-less.
### Data Model
```json
// Article document
{
"id": "article123",
"type": "article",
"title": "Understanding NoSQL",
"author": {
"id": "user456",
"name": "Jane Smith",
"email": "[email protected]"
},
"content": "Lorem ipsum dolor sit amet...",
"tags": ["database", "nosql", "tutorial"],
"published": true,
"publishedDate": "2025-05-01T10:30:00Z",
"comments": [
{
"id": "comment789",
"userId": "user101",
"userName": "Bob Johnson",
"text": "Great article!",
"timestamp": "2025-05-02T14:20:00Z",
"replies": [
{
"id": "reply456",
"userId": "user456",
"userName": "Jane Smith",
"text": "Thanks Bob!",
"timestamp": "2025-05-02T15:45:00Z"
}
]
}
],
"metadata": {
"viewCount": 1250,
"likeCount": 42,
"featuredImage": "/images/nosql-header.jpg",
"estimatedReadTime": 8
}
}
// Product document (completely different structure)
{
"id": "product789",
"type": "product",
"name": "Premium Ergonomic Chair",
"price": 299.99,
"categories": ["furniture", "office", "ergonomic"],
"variants": [
{
"color": "black",
"sku": "EC-BLK-001",
"inStock": 23
},
{
"color": "gray",
"sku": "EC-GRY-001",
"inStock": 14
}
],
"specifications": {
"weight": "15kg",
"dimensions": "65x70x120cm",
"material": "Mesh and aluminum"
}
}
```
### Spring Boot Implementation with MongoDB
```java
@Document(collection = "content")
public class ContentItem {
@Id
private String id;
private String type;
private Map<String, Object> data;
// Common fields can be explicit
private boolean published;
private Date createdAt;
private Date updatedAt;
// The rest can be dynamic
@DBRef(lazy = true)
private User author;
private List<Comment> comments;
// Basic getters and setters
}
// MongoDB Repository
public interface ContentRepository extends MongoRepository<ContentItem, String> {
List<ContentItem> findByType(String type);
List<ContentItem> findByTypeAndPublishedTrue(String type);
List<ContentItem> findByData_TagsContaining(String tag);
}
// Service for content management
@Service
public class ContentService {
private final ContentRepository contentRepository;
@Autowired
public ContentService(ContentRepository contentRepository) {
this.contentRepository = contentRepository;
}
public ContentItem createContent(String type, Map<String, Object> data, User author) {
ContentItem content = new ContentItem();
content.setType(type);
content.setData(data);
content.setAuthor(author);
content.setCreatedAt(new Date());
content.setUpdatedAt(new Date());
content.setPublished(false);
return contentRepository.save(content);
}
public ContentItem addComment(String contentId, Comment comment) {
ContentItem content = contentRepository.findById(contentId)
.orElseThrow(() -> new ContentNotFoundException("Content not found"));
if (content.getComments() == null) {
content.setComments(new ArrayList<>());
}
content.getComments().add(comment);
content.setUpdatedAt(new Date());
return contentRepository.save(content);
}
// Easily add new fields without migrations
public ContentItem addMetadata(String contentId, String key, Object value) {
ContentItem content = contentRepository.findById(contentId)
.orElseThrow(() -> new ContentNotFoundException("Content not found"));
Map<String, Object> data = content.getData();
if (data == null) {
data = new HashMap<>();
}
// Just update the field, no schema changes needed
data.put(key, value);
content.setData(data);
return contentRepository.save(content);
}
}
```
## Brief History of RDBs vs NoSQL
- Edgar Codd published a paper in 1970 proposing RDBs
- RDBs became the leader of DBs, mainly due to their reliability
- NoSQL emerged around 2009, companies like Facebook & Google developed custom solutions to handle their unprecedented scale. They published papers on their internal database systems, inspiring open-source alternatives like MongoDB, Cassandra, and Couchbase.
- The term itself came from a Twitter hashtag actually
The main reasons for a _'NoSQL wish'_ were:
- Need for horizontal scalability
- More flexible data models
- Performance optimization
- Lower operational costs
However, as mentioned already, nowadays RDBs support these things as well, so the clear distinctions between RDBs and document stores are becoming more and more blurry. Most modern databases incorporate features from both.
https://redd.it/1kph1lf
@r_devops
Map<String, Object> data = content.getData();
if (data == null) {
data = new HashMap<>();
}
// Just update the field, no schema changes needed
data.put(key, value);
content.setData(data);
return contentRepository.save(content);
}
}
```
## Brief History of RDBs vs NoSQL
- Edgar Codd published a paper in 1970 proposing RDBs
- RDBs became the leader of DBs, mainly due to their reliability
- NoSQL emerged around 2009, companies like Facebook & Google developed custom solutions to handle their unprecedented scale. They published papers on their internal database systems, inspiring open-source alternatives like MongoDB, Cassandra, and Couchbase.
- The term itself came from a Twitter hashtag actually
The main reasons for a _'NoSQL wish'_ were:
- Need for horizontal scalability
- More flexible data models
- Performance optimization
- Lower operational costs
However, as mentioned already, nowadays RDBs support these things as well, so the clear distinctions between RDBs and document stores are becoming more and more blurry. Most modern databases incorporate features from both.
https://redd.it/1kph1lf
@r_devops
Reddit
From the devops community on Reddit: Relational vs Document-Oriented Database for Software Architecture
Explore this post and more from the devops community
🌐 Open Source ThousandEyes Alternative — Feedback Wanted on My Network Observability Platform (v1)
### 🌐 Built an Open Source ThousandEyes Alternative — Feedback Wanted on My Network Observability Platform
Hey everyone 👋
I’ve been working on an open source Network Observability Platform, inspired by ThousandEyes, and I’m looking for community feedback, issues, and suggestions before releasing version 3.
🔗 GitHub (v1): https://github.com/shankar0123/network-observability-platform
---
### 🧰 What It Does
This platform provides distributed synthetic monitoring from multiple Points of Presence (POPs), using:
✅ ICMP Ping
✅ DNS resolution
✅ HTTP(S) checks
🔜 Traceroute / MTR (Planned)
✅ Passive BGP analysis via pybgpstream
Data is streamed via Kafka, processed into Prometheus, and visualized using Grafana. Everything is containerized with Docker Compose for local testing.
---
### 💡 Why I Built This
I needed a flexible, self-hostable way to:
- Test DNS/HTTP/ICMP reachability from globally distributed agents
- Correlate it with BGP route visibility
- Catch outages, DNS failures, or hijacks before customers feel them
- Deploy across edge POPs, laptops, VMs, or physical nodes
---
### ⚙️ Current Stack
- Canaries (ICMP/DNS/HTTP) in Python
- Kafka for decoupled message brokering
- Kafka Consumer → Prometheus metrics
- BGP Analyzer using pybgpstream
- Prometheus + Grafana + Alertmanager for visualization & alerting
---
### 🔄 Roadmap for v3 (In Progress)
I’m currently working on:
- 🚫 Replacing Docker with systemd + cron for long-running, stable canaries
- 📦 Integrating InfluxDB for lightweight edge metrics
- 🌍 Adding MTR/Traceroute support (using native tools or scamper)
- 🗺️ Building Grafana geo-maps and global views
- 🔐 Adding Kafka security, auth, TLS, hardened Grafana
- 🚨 Configurable alerting (high latency, BGP withdrawals, DNS failures)
- 🧱 Using Terraform for scalable POP provisioning
- 🛠️ Using Ansible to deploy and maintain canaries across multiple POPs
---
### 💬 Would Love Feedback On
- Is the v1 architecture solid for local/dev usage?
- Any design flaws or anti-patterns I should fix before pushing v3?
- Has anyone tried building something similar — what worked, what didn’t?
- Would anyone be interested in using or contributing?
---
This is a labor of love — for infra nerds, DDoS mitigation engineers, homelabbers, and folks who care about observability, reachability, and route visibility.
If you hit any snags getting it running or have suggestions, I’m all ears!
Thanks so much for checking it out!
https://redd.it/1kpjml4
@r_devops
### 🌐 Built an Open Source ThousandEyes Alternative — Feedback Wanted on My Network Observability Platform
Hey everyone 👋
I’ve been working on an open source Network Observability Platform, inspired by ThousandEyes, and I’m looking for community feedback, issues, and suggestions before releasing version 3.
🔗 GitHub (v1): https://github.com/shankar0123/network-observability-platform
---
### 🧰 What It Does
This platform provides distributed synthetic monitoring from multiple Points of Presence (POPs), using:
✅ ICMP Ping
✅ DNS resolution
✅ HTTP(S) checks
🔜 Traceroute / MTR (Planned)
✅ Passive BGP analysis via pybgpstream
Data is streamed via Kafka, processed into Prometheus, and visualized using Grafana. Everything is containerized with Docker Compose for local testing.
---
### 💡 Why I Built This
I needed a flexible, self-hostable way to:
- Test DNS/HTTP/ICMP reachability from globally distributed agents
- Correlate it with BGP route visibility
- Catch outages, DNS failures, or hijacks before customers feel them
- Deploy across edge POPs, laptops, VMs, or physical nodes
---
### ⚙️ Current Stack
- Canaries (ICMP/DNS/HTTP) in Python
- Kafka for decoupled message brokering
- Kafka Consumer → Prometheus metrics
- BGP Analyzer using pybgpstream
- Prometheus + Grafana + Alertmanager for visualization & alerting
---
### 🔄 Roadmap for v3 (In Progress)
I’m currently working on:
- 🚫 Replacing Docker with systemd + cron for long-running, stable canaries
- 📦 Integrating InfluxDB for lightweight edge metrics
- 🌍 Adding MTR/Traceroute support (using native tools or scamper)
- 🗺️ Building Grafana geo-maps and global views
- 🔐 Adding Kafka security, auth, TLS, hardened Grafana
- 🚨 Configurable alerting (high latency, BGP withdrawals, DNS failures)
- 🧱 Using Terraform for scalable POP provisioning
- 🛠️ Using Ansible to deploy and maintain canaries across multiple POPs
---
### 💬 Would Love Feedback On
- Is the v1 architecture solid for local/dev usage?
- Any design flaws or anti-patterns I should fix before pushing v3?
- Has anyone tried building something similar — what worked, what didn’t?
- Would anyone be interested in using or contributing?
---
This is a labor of love — for infra nerds, DDoS mitigation engineers, homelabbers, and folks who care about observability, reachability, and route visibility.
If you hit any snags getting it running or have suggestions, I’m all ears!
Thanks so much for checking it out!
https://redd.it/1kpjml4
@r_devops
GitHub
GitHub - shankar0123/network-observability-platform: This project provides a distributed system for synthetic network monitoring…
This project provides a distributed system for synthetic network monitoring and BGP analysis, inspired by platforms like ThousandEyes. - shankar0123/network-observability-platform
First HomeLab Setup
Yeah I'm just about to try and install my Mikrotek router I'm not wanting to make a high availability cluster... yet.
My main aim is to ensure the long standing elements of my network are hosted on the Router itself. DHCP & DNS management, firewall and network admin.
RouterOS 7 has support for docker, so I'm aiming to make all the homelab docker containers be there or on a high speed flash drive.
I'm new to networking this seems intuative to me but most people seem to host their network management on their PC's docker hosts. Is there a reason for that? Is it better to be on a seperate machine
I'm hoping to:
1. Get a public IP from my ISP
2. Bridge mode my Plusnet hub
3. Install all network management apps on the Router itself
4. Router OS has docker support I would likely want to host my Portainer/Rancher on there along with my Keycloak, HeadScale, Home Assistant and Traefik.
This seems to be the logical thing so that no matter what OS or machine I have as a computer for media or other needs I can point to the Router for all network management. However I never see people doing this. Most have their network management on a second machine. Is there a reason for this?
Do people have recommendations on why NOT to have all the HomeLab admin on the Router/Firewall?
Secondly I'm wanting to have all the Docker containerised apps on a local network available network.
https://redd.it/1kpnkqa
@r_devops
Yeah I'm just about to try and install my Mikrotek router I'm not wanting to make a high availability cluster... yet.
My main aim is to ensure the long standing elements of my network are hosted on the Router itself. DHCP & DNS management, firewall and network admin.
RouterOS 7 has support for docker, so I'm aiming to make all the homelab docker containers be there or on a high speed flash drive.
I'm new to networking this seems intuative to me but most people seem to host their network management on their PC's docker hosts. Is there a reason for that? Is it better to be on a seperate machine
I'm hoping to:
1. Get a public IP from my ISP
2. Bridge mode my Plusnet hub
3. Install all network management apps on the Router itself
4. Router OS has docker support I would likely want to host my Portainer/Rancher on there along with my Keycloak, HeadScale, Home Assistant and Traefik.
This seems to be the logical thing so that no matter what OS or machine I have as a computer for media or other needs I can point to the Router for all network management. However I never see people doing this. Most have their network management on a second machine. Is there a reason for this?
Do people have recommendations on why NOT to have all the HomeLab admin on the Router/Firewall?
Secondly I'm wanting to have all the Docker containerised apps on a local network available network.
https://redd.it/1kpnkqa
@r_devops
Reddit
From the devops community on Reddit
Explore this post and more from the devops community