The hidden costs of additions to a system
Source: Dev.to
The natural bias towards adding is strong and pervasive
Software engineers who have never been exposed to the cost of their “additions”—often those who have not worked at an early‑stage startup—tend to add complexity instead of reducing it (or at least maintaining it).
They rarely pay the price of maintaining what they added because, in larger organizations, they often:
- Move teams frequently, causing other people to pay the bill they created.
- Rely on DevOps, Security, or Finance teams to offload part of the cost.
- Focus on delivering tickets rather than delivering value, so they don’t realize that their current work is a consequence of decisions made months earlier and could have been avoided.
Systemic thinking allows engineers to see the impact of their additions not only in the short term but also in the long term, affecting both the technical system and the broader organizational “people system.”
When performing a cost‑benefit analysis of a solution, you must account for hidden costs—even if you are not the one paying them later. As a value creator, your goal is to save time and reduce stress for those around you.
Common additions with hidden costs
- A new database
- A new programming language
- A new framework
- A new pattern in the codebase
- A new external service
- A new server‑to‑server communication protocol (e.g., REST, SOAP, GraphQL, gRPC) or pattern (e.g., sync, event‑driven)
The most neglected hidden costs
- Higher onboarding cost for new team members
- Higher context‑switching cost when working on that codebase or system
- Larger surface area of things that can break
- Larger surface area of things you need to monitor
- Extra monitors you need to set up
- Extra alerts you need to configure
- Additional security patches and updates you must stay on top of
- Unknown‑unknowns that can cause outages
If you add up all of those hidden costs, it becomes clear that you need a really strong reason to justify any addition. That reason should align with the company’s long‑term goals and objectives, not just the optimal solution for the ticket at hand.
Extreme example: Could a single PostgreSQL instance suffice?
“No way, I handle payment processing at a high scale and I need a queuing system.”
Answer: PostgreSQL natively supports queuing via tables storing payment events and consumers usingSELECT FOR UPDATE SKIP LOCKEDsemantics.
“Okay, but I need Elasticsearch for fuzzy text search.”
Answer: Thepg_trgmextension provides fuzzy and partial matching, ranking, and even stemming directly in SQL.
“We need MongoDB for its flexible JSON documents.”
Answer: PostgreSQL’sJSONBtype lets you query nested structures, index them, and join them with relational data.
PostgreSQL alternatives for common needs
| Need | PostgreSQL solution |
|---|---|
| Background jobs | jobs table + SELECT FOR UPDATE SKIP LOCKED |
| Recurring jobs | pg_cron for native scheduling |
| Pub/Sub | LISTEN / NOTIFY for lightweight real‑time notifications |
| Analytics | Window functions, CTEs, and materialized views |
| Columnar storage | cstore_fdw for analytical queries |
| Machine learning | MADlib for in‑database regressions and clustering |
| ETL & pipelines | http_fdw + pg_cron for scheduled ingestion & transformation |
| Caching layer | UNLOGGED tables or materialized views as durable caches |
| Geospatial queries | PostGIS for coordinates, distances, and shape operations |
| Vector search | pgvector for embeddings and similarity search |
| Policy enforcement | Row‑Level Security (RLS) for user‑level access rules |
| Configuration store | Versioned config tables with constraints and history |
| Auditing | Triggers + JSONB logs for a full change history |
| REST API | PostgREST automatically exposes CRUD endpoints |
| GraphQL API | Hasura for instant GraphQL on top of PostgreSQL |
| File storage | bytea or large objects for small‑to‑medium files |
Again, this is an extreme example and does not imply that keeping everything in PostgreSQL is the right answer for every use case. It simply illustrates what’s possible and challenges you to ask, for any given feature:
“How can I achieve this business or technical objective while introducing the minimum amount of complexity, now and for the long run, for me and for my peers?”
Closing thought
When evaluating new additions, always weigh the hidden costs against the long‑term value they deliver. Aim for the simplest solution that meets the objective, and reserve more complex additions for cases where they are truly justified by the organization’s strategic goals.