egabriel.dev · tty1 · simulated boot (illustrative)
  1. GE-BIOS v2.6 · egabriel.dev portfolio platform
  2. CPU0: backend/cloud engineer · distributed systems
  3. Memory test: 16384M ... OK
  4. Boot device: static output · booting kernel
  5. [ 0.000000] portfolio-kernel 1.0 (static output) #1 SMP
  6. [ 0.018342] edge: HTTPS terminated at hosting provider[OK ]
  7. [ 0.041207] edge: security headers loaded[OK ]
  8. [ 0.052911] lsm: content-security-policy enforced (self + hashes)[OK ]
  9. [ 0.077915] fs: mounted version-controlled content[OK ]
  10. [ 0.112906] runtime: interactive components registered, loaded on demand[OK ]
  11. [ 0.163380] net: public API mapped at /api[OK ]
  12. [ 0.187004] api: contract published at /api/openapi.json[OK ]
  13. [ 0.201377] storage: no block device found (no database, by design)[SKIP]
  14. [ 0.224551] mail: contact delivery online[OK ]
  15. [ OK ]Started systems.service
  16. [ OK ]Started principles.service
  17. [ OK ]Started about.service
  18. [ OK ]Started resume.service
  19. [ OK ]Started contact.service
  20. [ OK ]Reached target portfolio (rack wall online)
Welcome...
Skip to content
~/principles

Complexity should be earned.

I don't add architecture to look impressive. Every service, queue, cache, and abstraction should exist because a specific constraint requires it. When it doesn't, I don't add it. This portfolio is built the same way.

  1. Principle 01

    Start simple

    Start with the simplest architecture capable of solving the problem.

    I don't introduce microservices because they make architecture diagrams look impressive. Complexity should solve a real constraint.

    Simulation · one payment request, two architectures
    ClientIdentityPaymentsEstatePostgreSQL
    Deployables
    1
    Network calls / request
    0
    Databases
    1
    Places it can fail
    2

    Microservices are the right answer when teams or scaling needs force them apart. Until then, they are four extra network calls that can each time out.

  2. Principle 02

    Design for failure

    Networks fail. APIs time out. Messages can be delivered twice. Third-party systems become unavailable.

    Production software should expect these conditions rather than treating them as exceptional.

    Simulation · a dependency that fails 30% of first attempts
    1. Request 1: not sent
    2. Request 2: not sent
    3. Request 3: not sent
    4. Request 4: not sent
    5. Request 5: not sent
    6. Request 6: not sent
    7. Request 7: not sent
    8. Request 8: not sent
    9. Request 9: not sent
    10. Request 10: not sent
    succeeded 0/0✓ ok · ↻ recovered by retry · ✕ failed

    Retries turn transient failures into successes — but every retry is another call to the dependency, which is why they need backoff, limits, and idempotency.

  3. Principle 03

    Observability is a feature

    If production fails, the system should tell you what failed, where, when, which request triggered it, which dependencies were involved — and whether it can recover.

    Logging, tracing and metrics are part of system design.

    Simulation · one failure, two log lines
    09:41:09 ERROR Something went wrong: The operation has timed out.
    • What failed? — answerable
    • Where did it fail? — not answerable
    • When did it fail? — answerable
    • What request triggered it? — not answerable
    • What dependencies were involved? — not answerable
    • Can it recover? — not answerable
  4. Principle 04

    Data is architecture

    Database decisions are architecture decisions.

    Before choosing a storage technology, I think about:

    • — Transactions
    • — Indexes
    • — Query patterns
    • — Consistency
    • — Concurrency
    • — Relationships
    • — Data lifecycle
    Illustration · query plan for a dashboard query
    SELECT * FROM payments
    WHERE estate_id = 42
    ORDER BY created_at DESC
    LIMIT 20;
    Limit  (rows=20)
      ->  Sort  (sort key: created_at DESC)
            ->  Seq Scan on payments
                  Filter: (estate_id = 42)
                  rows read: 2,400,000
    execution time1,284 ms

    Same database, same query, three orders of magnitude apart. Access patterns belong in the design, not in a post-launch fire drill. (Illustrative numbers.)

  5. Principle 05

    Understand the trade-off

    There is rarely one universally correct architecture.

    Decisions depend on:

    • — Constraints
    • — Team
    • — Traffic
    • — Cost
    • — Reliability
    • — Development speed
    • — Operational complexity
    • — Maintainability

    The goal is not maximum sophistication. The goal is the appropriate trade-off.

    Interactive · my rough take for a small team
    Operational complexity
    Low
    Cost at low traffic
    Medium
    Independent scaling
    Low
    Team autonomy
    Medium
    Early development speed
    High
    Local debugging
    High

    Every option wins somewhere and loses somewhere. The job is picking the losses you can live with.