Reddit DevOps
267 subscribers
1 photo
31K links
Reddit DevOps. #devops
Thanks @reddit2telegram and @r_channels
Download Telegram
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
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
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

{
"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,
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
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

// 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,
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
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
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)
.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
🌐 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
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
What’s one thing you wish you’d done earlier in your cloud career?

Looking back, I really wish I’d taken the time to actually read the AWS documentation.

I wasted so much time trying to patch things together without understanding what was really going on. Once I slowed down and started building small, deliberate projects—everything clicked faster.

It got me thinking:
Everyone seems to have that one "a-ha" moment or regret about how they approached learning cloud or DevOps.

What’s yours?
If you could start again from day one, what would you do differently?

https://redd.it/1kpoyl3
@r_devops
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/1kpnjpy
@r_devops
When did Docker finally click for you?

For me, the moment I cloned a repo, ran docker compose up, and had a full app with a DB, cache, and frontend running, without installing anything locally, it finally made sense. What was your moment?

https://redd.it/1kproue
@r_devops
Discussion: Devops prep for AI invasion

Devops/Platform engineer with ~4 yrs of exp (5 if you count internships) and I’m wondering how y’all are prepping for the”AI” wave. I know this is a loaded term that has been used as marketing tool and an excuse for “organizational realignment” for companies trying to thin the herd of development. While a lot of us in the “ops” space have been saf(er) than run of the mill app developers, even still, how are you preparing for AI to inevitably branch off into our territory? I use it daily, primarily as an upskill tool to help bridge some gaps in my knowledge, especially since my org uses all of the big 3 cloud providers, and k8s in each one. I have found that while AI is great for the basics of script writing, pipeline/helm templating and whatnot, it really struggles with the SRE side of things. Usually our bugs require a human touch to solve. I imagine this will go away as AI gets more intuitive and orgs allow more internal AI access to logging, metrics and architecture patterns.

My question is, how do we stay relevant among all this? I’ve considered re-classing as a net engineer since AI cant plug in cables (yet) but I’m wondering if anyone else has ideas or options for safe places to go from here. I’ve resigned myself to the fact that my CS degree has become all but worthless in this economy, and I’m trying to figure out where to go from here to keep all the hard work I’ve invested from going to waste flipping burgers.

TL;DR
Ops seems saf(er) from the AI takeover for now.. how are y’all preparing for the inevitable?


Edit:
Saf(er) meaning for those who are currently employed.. for those who are hunting in this market.. my deepest sympathies. You are all great, under appreciated and deserve better.

https://redd.it/1kpunic
@r_devops
I created a video giving an overview of how to manage secrets using sops, a tool that allows you to commit encrypted secrets to a repo and conveniently decrypt and pass them to an application

Video link: https://www.youtube.com/watch?v=OQyKFhewX\_k

Sops: https://getsops.io

I've used sops in a day job before and it was great, and I've really enjoyed discovering all the little features I didn't know about while researching this video. Hopefully it'll be useful information to someone.

https://redd.it/1kpv8l3
@r_devops
Is DevOps even a junior-level job?

I’ve been thinking about this a lot. Is DevOps really something a junior should do straight out of school or bootcamp?

Wouldn’t it make more sense to spend 3 to 5 years as either a pure sysadmin or pure developer first? DevOps touches so many areas:
Infrastructure, CI/CD, security, monitoring, automation, and without a solid foundation, it feels like you’re constantly drowning.

Unless you have a strong mentor guiding you, things can spiral quickly. Without that support, it’s less of a job and more of a daily panic. Curious how others see this. Should DevOps even be offered as a junior role, or is it something you grow into later?

https://redd.it/1kpx6t0
@r_devops
Is it possible and/or likely?

Hello all, I am pursuing an associates degree in software engineering in my local community college. I’m making this post to ask if it’s gonna be possible or if it’s even likely to get hired with just an associates degree and maybe if I put some extra time in to making a good portfolio and/or website to display projects and games that I will create? Also any tips for this would be welcomed and much appreciated. Thank you all so much!

https://redd.it/1kpx196
@r_devops
Found 3 production systems this week with DB connections in plain text zero SSL, zero cert validation. Still common in 2025.

I’ve been doing cloud security reviews lately and I keep running into the same scary pattern:
• Apps calling PostgreSQL or MySQL with no SSL
• Connection strings missing sslmode=require or verify-full
• No cert validation. Nothing.

This is internal traffic in production.

Most teams don’t realize this opens them to:
• Credential theft
• Data interception
• MITM attacks
• Compliance nightmares (GDPR, HIPAA, etc.)

What’s worse? This stuff rarely logs. You only find out after something weird happens.

I’m curious how does your team handle DB connection security internally?

Do you enforce SSL by policy? Use IAM auth? Rotate DB creds regularly?


Would love to hear how others are approaching this always looking to learn (and maybe help).


https://redd.it/1kpz5zu
@r_devops
Monolith vs. Microservices – Need Advice for My App Architecture

Hi all,

Im in the early stages of planning the architecture for my app, and Im torn between going with a monolithic or microservices approach. I could use some insight from people who’ve worked with either (or both).

# Context:

The entire app would be made in go with 2 postgres databases and one backup for the main data that my app uses. If the app was microservice based then the ipc would be handled via grpc with a rest gateway all written in go.

My app has two main features for now:

Scheduling feature – low intensity
Analytics feature – CPU intensive. most of it is handled in go but a small ML part of it is handled in python.

Im planning to add more features later on, depending on user feedback and demand.

# What i would like to have in an ideal scenario:

Easy scalability as the app grows
Ability to update features without having to redeploying the entire app
Clean codebase that new developers can easily contribute to
Cost efficiency (hosting on GCP)

I don’t expect a lot of users at first (maybe 5 initially), so I was considering starting small with a low-core VPS and hosting the backend there. It’s a side project, so there's no strict timeline to finish. if i were to choose the grpc microservice approach id just put the entire app in the same vps using docker compose

# My Questions:

What are the pros and cons of monolithic vs. microservices in this kind of setup?
Based on what I’ve shared, which approach would you recommend and why?

Thanks in advance to anyone who shares their experience or thoughts

https://redd.it/1kq154z
@r_devops