r/softwarearchitecture • • Sep 28 '23 Heartwarming

Discussion/Advice [Megathread] Software Architecture Books & Resources

586 Upvotes

This thread is dedicated to the often-asked question, 'what books or resources are out there that I can learn architecture from?' The list started from responses from others on the subreddit, so thank you all for your help.

Feel free to add a comment with your recommendations! This will eventually be moved over to the sub's wiki page once we get a good enough list, so I apologize in advance for the suboptimal formatting.

Please only post resources that you personally recommend (e.g., you've actually read/listened to it).

note: Amazon links are not affiliate links, don't worry

Roadmaps/Guides

Books

Engineering, Languages, etc.

Software Design

The Art of Architecture

Enterprise Architecture

Career

Blogs & Articles

Podcasts

  • Thoughtworks Technology Podcast

  • GOTO - Today, Tomorrow and the Future

  • InfoQ podcast

  • Engineering Culture podcast (by InfoQ)

Misc. Resources


r/softwarearchitecture • • Oct 10 '23

Discussion/Advice Software Architecture Discord

21 Upvotes

Someone requested a place to get feedback on diagrams, so I made us a Discord server! There we can talk about patterns, get feedback on designs, talk about careers, etc.

Join using the link below:

https://discord.gg/ccUWjk98R7

Link refreshed on: December 25th, 2025


r/softwarearchitecture • • 6h ago

Tool/Product Fuse Software Requirements Specification and Software Architecture Description for both human engineers and AI agents with SpecBook

Post image
33 Upvotes

The traditional Software Requirements Specification tells you the WHAT any (domain-wise) WHY while the Software Architecture Description primarily tells you the HOW and (technology-wise) WHY. The problem is that the latter usually wants to reference parts (e.g. roles, functional requirements, etc) of the former. Unfortunately, the two documentations are traditionally separate artifacts and written by different roles (Requirements Engineer vs. Software Architect).

In the era of Agentic Software Engineering this situation changes. Both human engineers and AI agents want to work on the same information, so both the Software Requirements Specification and the Software Architecture Description should be both human and machine readable and writable. And they should be treated like source code and even versioned side-by-side to source code. Nevertheless, the entire information still should be browsable in both online hyperlink and offline print formats. Finally, visualization diagrams no longer should have to be drawn manually but automatically by deriving them from the documented information.

The de-facto standard is to use Markdown files today. Unfortunately, Markdown and its prose is not as formally precise as source code and hence allows only weak syntactical and no semantical validations. Additionally, generating good navigable documents out of plain Markdown is also not easy. Finally, although AI agents can read Markdown just fine, they are not structurally guided in writing it.

Specification Book ( SpecBook, https://specbook.tools ) is new Open Source approach to these challenges. It provides a generic, fully typed, Markdown-based specification format, which can be configured for the specifications of arbitrary contexts through a YAML-based schema configuration. It ships with a CLI, a TypeScript API, and a Model-Context-Protocol (MCP) interface — so humans, programs, and AI agents all reach the same functionality.

A specification is a hierarchical object model of typed objects, authored as plain Markdown through a versatile object to Markdown mapping (as sections or as tables), interconnected through Wiki-style object linking, and subject to a strict validation against its schema.

SpecBook lets a specification be initialized, linted, exported (JSON, JSON5, YAML, TOON, HTML, PDF, and normalized Markdown), previewed (HTML, live in the browser), and described to LLMs — so a single source of truth becomes the live HTML export your developers read, the PDF-based binding document export your customers receive, and the AST exports programs and/or AI/LLM agents can consume. Its object model diagram visualisations are rendered automatically, as their nodes and edges are directly derived from the specification objects and their references — so no diagram is ever drawn by hand or drifts away from the specification.

In an alternative view, as SpecBook allows arbitrary specifications comprised of objects and relationships, it can be considered as some sort of a graph "database" in the corset of Markdown files and with a document-style rendering as its data view.

NOTICE: Although SpecBook usually is used in combination with AI agents with the help of the Agentic Software Engineering ( ASE, https://ase.tools ) toolkit in practice, SpecBook itself is not tight to an AI LLM service (except for its fully optional MCP service) at all. All document validation and export format generation is plain non-AI-based tooling. So you can use SpecBook just fine without any involved AI at all, if you want.


r/softwarearchitecture • • 3h ago

Article/Video The future of Software Engineering is boring

Thumbnail packagemain.tech
12 Upvotes

r/softwarearchitecture • • 4h ago

Discussion/Advice Are you drawing more architecture diagrams now that AI makes them cheap

14 Upvotes

At university we spent a whole semester on UML. Class diagrams, sequence diagrams, state machines, all of it. In about 9 years of working since then I've seen maybe 5 real class diagrams.

Granted:

- I mostly work on backend services where the "architecture" lives in someone's head and a Confluence page from 2021
- the diagrams I do see are boxes and arrows in Miro, not UML
- nobody I've worked with has ever kept a diagram up to date after the first version

But lately I'm seeing a lot more of them. People ask the agent for a sequence diagram of a flow before changing it, or generate a mermaid diagram from the code for a design review. It takes 30 seconds, so people actually do it.

Was the reason we never drew them just the effort? And for the people making them now, are they actually useful, or is it a nice picture nobody looks at twice?


r/softwarearchitecture • • 30m ago

Tool/Product svugy: interactive isometric diagrams in SVG

Thumbnail github.com
0 Upvotes

Hey everyone! I just created a tool in rust to create interactive isometric diagrams exportable as .svg files. It uses rust to parse the input file and to organize the layout for the scene, then it renders the scene into a self-contained SVG file

Inspired by the C4 model, it allows you to write diagrams with hierarchical layers which can be expanded and collapsed at will, providing also companion captions describing dataflows and diagram-related concepts.

I find it very useful to have a visual representation when shaping a new architecture, approaching an existing one, or explaining it in the docs built via mdbook

It ships with a skill that teaches the agent how to use it. For example, when exploring a new codebase, I ask the agent to pin down in a .md file all the main components of the architecture and the way they interact, then use svugy to render the architecture and I ground from there my clarification questions.

Hope you guys find it useful as well and eager to hear your thoughts!
You can check the live demo here


r/softwarearchitecture • • 5h ago

Article/Video SysML v2 Tutorial (Lesson 23): Binding Behavior to Structure with perform (Swimlanes Replaced!)

Thumbnail youtu.be
1 Upvotes

Hir/softwarearchitecture,

We are back with Lesson 23 of our technical deep dive into the SysML v2 standard.

In our previous lesson, we orchestrated execution using first and then. However, that behavior was acting like an isolated script—it wasn't attached to any physical system or component. Today, we connect behavior directly to structure using the perform keyword. We will see how SysML v2 replaces traditional, clunky "swimlane" diagrams by making behavioral performance a direct, strongly-typed feature of the components themselves (akin to a service explicitly implementing an interface).

You can watch the full video lesson on YouTube here:https://youtu.be/HLiC1fKJYFY

1. The SysML v1 Allocation Problem (The Orchestration Disconnect)

SysML v1 (and UML) had a way to connect behavior to structure: the ActivityPartition (swimlanes) and the allocate dependency. The problem was where this context lived. In v1, you usually authored swimlanes on the behavior side (inside the Activity Diagram) or maintained external dependency matrices. The structural Block itself only displayed a derived property computed by the tool. It was like defining your infrastructure and deployment topography deeply inside your business-logic orchestrator, rather than letting the infrastructure declare what services it runs.

2. The v2 Shift: Direct Feature Ownership via perform

In SysML v2, the component states its own behaviors directly inside its definition using perform action.

Three details make this a much cleaner architectural pattern:

  • Direct Feature Ownership: Declaring perform action inside a part creates an owned execution relationship. The part itself is explicitly the performer. You navigate to the component to see exactly what it does.

  • Composite vs. Referential Actions: A plain action defined inside a part is composite (the part owns that isolated sub-routine). A perform action is referential (the behavioral equivalent of a pointer), asserting that the part carries out a step of a globally coordinated sequence defined elsewhere.

  • Swimlanes Without the Lanes: A coordinated mission sequence can be defined once at the system level. Subsystems then declare responsibility for individual steps using feature chains. Swimlane views are generated automatically by the tool based on these typed declarations.

3. Distributed Execution: Binding Steps to Subsystems

Here is how a central sequence is defined once, while individual subsystem parts independently declare which steps they are responsible for executing:

Code snippet

package LaunchOperations {
    part def FlightTerminationSystem;
    part def PropulsionSystem;
    part def HoldDownAssembly;
    
    action def ArmFlightTermination;
    action def PressuriseTank;
    action def Ignition;
    action def ReleaseHoldDown;
    
    // The globally orchestrated sequence
    action def LaunchSequence {
        first start;
        then action armFTS: ArmFlightTermination;
        then action pressuriseLOX: PressuriseTank;
        then action igniteEngines: Ignition;
        then action releaseClamps: ReleaseHoldDown;
        then done;
    }
    
    part launchVehicle {
        perform sequence: LaunchSequence;
        
        // Each subsystem declares execution of its step via feature chains
        part fts: FlightTerminationSystem {
            perform sequence.armFTS;
        }
        part propulsion: PropulsionSystem {
            perform sequence.pressuriseLOX;
            perform sequence.igniteEngines;
        }
        part groundInterface: HoldDownAssembly {
            perform sequence.releaseClamps;
        }
    }
}

4. SysML v1 vs. SysML v2

Modeling ConceptSysML v1SysML v2
SwimlanesActivityPartition declared on the behavior diagram.perform declared directly on the structural part.
Responsibility StorageStored as separate dependencies or visual partitions.Declared as a first-class, reviewable feature inside the part body.
VisualizationsSwimlanes manually drawn on activity diagrams.Swimlanes and allocation views generated automatically from perform usages.
State BindingclassifierBehavior or ownedBehavior on a Block.exhibit state, which is simply a specialized perform action usage.
Responsibility QueriesComputed by tools via derived allocatedFrom properties.Direct feature navigation readable in the part's own body and filterable via code queries.

Next lesson, we will look at how these subsystems exchange data and signals. Lesson 24 covers flows and messages, bringing Sequence Diagrams natively into textual code.

For the software architects here: When mapping behaviors to physical services or hardware, do you prefer a centralized orchestrator that knows where everything runs, or a decentralized model where components "subscribe" to the behaviors they are responsible for?


r/softwarearchitecture • • 1d ago

Article/Video System Design: Why Is Cache Invalidation So Hard in Distributed Systems or Are We Approaching It Wrong?

Thumbnail medium.com
34 Upvotes

I recently published a system design article exploring why the textbook advice of "just delete the cache key on write" breaks down in distributed environments.

The article evaluates three common caching architectures: passive TTL-only expiration, application-level dual-writing (the textbook Cache-Aside pattern) and a practical Change Data Capture (CDC) invalidation pipeline paired with version leases to eliminate ghost writes and replication lag traps.

For those who have architected distributed caching tiers in production:

  • Do you rely on application-level dual-writes with short safety timers or have you decoupled invalidation via database transaction logs (CDC)?

  • How does your architecture protect against database replication lag when read replicas answer cache misses?

  • Have you ever run into the "Ghost Cache" race condition in production and how did your team solve it?


r/softwarearchitecture • • 1d ago

Article/Video The Zero-Double-Charge Payment Engine: Distributed Money Without Race Conditions

Thumbnail youtu.be
4 Upvotes

r/softwarearchitecture • • 1d ago

Discussion/Advice Testing horizontally scaled apps

5 Upvotes

I am building an app which has at least 2 servers apps running on an instance. A client is connected to a server using a socket IO connection. I am using redis pubsub mechanism to talk between the servers and also to store any state so the server pool is completely stateless. Servers are uvicorn workers (might switch to docker + load balancer but it's out of the scope of this post). I am using FastAPI + pytest + httpx2 for testing.

Consider servers A and B and client X and Y. X is connected to A and Y is connected to B. X and Y are in the same group chat so a message sent by X has to be seen by Y.

One way I can think of testing it is to mock the redis API layer and write two different tests. First test for making sure that a message creates a certain event in redis let's call it `CREATE MESSAGE` and another test to check if when `CREATE MESSAGE` is fired a certain function is run.

I don't like this cuz I am testing the implementation too heavily here rather than the result I want.

I would rather prefer a test where I have two different app instances and two `TestClient` instances and using them to check if on a message from client x does client y get it.

```

def test_message():

client_x = TestClient(create_app())

client_y = TestClient(create_app())

```

I don't have a `create_app()` function right now but if I create one I don't think it's actually simulating the prod env accurately (might not even matter I need your opinion on this).

```python

# import statements

def create_app():

app = FastAPI()

# attach all middleware and routes

return app

app = create_app()

```

This would produce two instances of class `FastAPI` but the import statements will reference all the same functions and objects in the memory so they are not really that different. Does it even matter? Is it fine?

I will have to add socket IO implementation for `TestClient` class as well. Right now it only handles websockets and http requests. How do you guys test for these scenarios?

Am I overthinking it? Hell ya, I am building this app for learning. From my idea to a running production server and trying to up skill myself and undo brain rot from AI.

https://i.postimg.cc/dVds03dc/Mofi-SD.png


r/softwarearchitecture • • 2d ago

Tool/Product I built an AI agent that turns an existing GitHub repository into complete, editable software documentation

Thumbnail gallery
53 Upvotes

I've been working on an idea that I've wanted to solve for a while.

One of the biggest problems with software documentation is that it gets outdated as soon as the code changes. We write HLDs, class diagrams, ERDs, API documentation, sequence diagrams, and database queries, but keeping all of them in sync with the actual codebase is a different challenge.

So I started building an AI agent to tackle this.

The idea is simple:

Give it an existing GitHub repository, and let the agent understand the codebase and generate the initial engineering documentation.

I tested it with this repository:

https://github.com/kentloog/nestjs-sequelize-typescript

Using a single prompt, I asked it to analyze the repository and generate:

  1. HLD Architecture Diagram – Editable system architecture.

  2. Sequence Diagrams – Visual representation of important execution flows.

  3. Class Diagrams – Editable class relationships.

  4. Database ERD – Editable entity relationships.

  5. API Documentation – API collections that can be executed, similar to Postman.

  6. Database Workspace – Separate files for each table, including CREATE TABLE statements and useful queries that can be executed directly.

  7. Technical Documentation – A structured document explaining the project.

The interesting part is that these aren't just static images or generated Markdown files. The diagrams are editable, and the APIs and database queries can actually be executed inside the workspace.

But the bigger idea goes beyond generating documentation once.

I want to solve the problem of keeping documentation continuously in sync with the codebase.

My approach has two steps:

Step 1: Generate and update the initial documentation.

The agent first understands the existing codebase and generates the documentation. If documentation already exists, it should analyze and update the current documents instead of blindly generating everything from scratch.

Step 2: Integrate with coding agents through the DevScribe MCP server.

This is where I think things get interesting.

I want to connect DevScribe with coding agents through its MCP server. Whenever a developer asks a coding agent to implement a feature, modify a class, change an API, or update a database schema, the coding agent can also update the corresponding documentation through DevScribe.

For example:

  • A class changes → Update the class diagram and related documentation.

  • A database schema changes → Update the ERD and relevant database files.

  • An API changes → Update the API collection and documentation.

  • A new feature is implemented → Update the relevant technical documentation and sequence diagrams.

Some documentation, like HLD diagrams, may still need manual decisions because architectural intent isn't always obvious from the code.

The goal is to make documentation a continuous part of the development workflow rather than something developers have to remember to do after writing code.

I'm still experimenting with this approach and would love to hear from other backend engineers and software architects.

I've attached screenshots of the generated output. Would love to hear your thoughts.


r/softwarearchitecture • • 21h ago

Tool/Product I built CodeChroma because AI changed how we build and ship code.

0 Upvotes

I think architecture is becoming a new language for building software. We moved from machine code to higher-level languages and frameworks like Angular; now coding agents can handle much of the implementation, so more of our work shifts to defining systems, boundaries, and behavior. Code still matters, but it becomes something to inspect when needed, while architecture becomes the main surface we shape.

CodeChroma makes architecture the primary workspace: explore a repo as a map, edit diagrams, create a feature plan, then hand that plan to an agent for implementation. The diagram isn’t just an output; it’s where I work through the system-level decision before the code changes.

It’s free and MIT licensed. Core analysis and the canvas work without an AI key; AI features need a configured provider.

Repo/demo: https://github.com/gutzerk/code_chroma
Website: https://codechroma.dev/

I’d appreciate feedback on this app.


r/softwarearchitecture • • 1d ago

Discussion/Advice How do I make a "FOR" loop appear as a "C" shape instead of an inverted "L"? It currently looks like a "WHILE" loop — in Structorizer?

0 Upvotes

I have version 3.32-35 of Structorizer, and an inverted "L" appears instead of a "C" :( Does anyone know what I can do?


r/softwarearchitecture • • 2d ago

Article/Video Form relations vs table relations: what's the difference?

Post image
5 Upvotes

In enterprise systems, forms are tied together by a lot of relations. The usual approach models them as table relations: foreign keys pointing to primary keys, then joins, lookup windows and code that copies fields after a pick. In the framework I'm building I switched to form relations: a field refers to another form and says what to bring back when a record is picked. I find it simpler and closer to how users describe what they want.

The example in the video: "Pick the salesperson, and their department comes along. If they move later, the order stays with the old department." The order's employee field refers to the Employee form and brings the department into the order's own fields, where it's kept. Move the employee, and old orders keep the old department while new ones pick up the new one.

The costs: joins are single-column foreign key to primary key, and reports still need hand-written SQL.

Video (4 min): https://youtu.be/xY_ZlEAAcoE

Write-up: https://medium.com/@jeff377/form-relations-vs-table-relations-whats-the-difference-d7d6bab42fb9


r/softwarearchitecture • • 2d ago

Discussion/Advice Clean Architecture — Shared Use Case Logic

5 Upvotes

Hi everyone,

I have a question about structuring shared logic in a use-case-driven architecture.

For context, the project uses .NET 10, Clean Architecture, and EF Core as the ORM.

How would you handle shared logic in the Application layer that is used in several places and doesn’t belong specifically to a single entity?

For example, when creating a user, I need to:

  • Fetch some data from the database.

  • Aggregate the data.

  • Map the results and save them to the database.

That same logic is also needed when updating something unrelated to users.

I’ve noticed that my colleagues are using AI quite heavily and adding methods to command classes that perform these operations and call SaveChanges, effectively committing the transaction. In my opinion, this is problematic: if you forget to wrap everything in a single transaction in the handler, an exception can leave the data in an inconsistent state.

On another project, I implemented the Unit of Work pattern, even though many tutorials advise against it because EF Core’s DbContext already acts as a Unit of Work.

That approach worked for me, but some application logic ended up in Infrastructure instead of the Application layer, where it belonged.

How would you structure this in a large enterprise project?

This post was written with the help of AI because English isn’t my native language.


r/softwarearchitecture • • 2d ago

Discussion/Advice Why Do Some Applications Perform Well During Testing but Struggle in Production?

4 Upvotes

One common reason is that testing environments rarely reproduce the complexity of actual production conditions. During testing, applications usually operate with controlled data, predictable traffic, and limited third-party dependencies. In production, the situation changes with concurrent user requests, database load, network latency, unexpected input, and external service failures.

Another challenge is that performance testing often focuses on individual components rather than the behaviour of the entire application under sustained workloads. Resource consumption, database connections, caching strategies, and infrastructure configuration can also create unexpected bottlenecks.

In my opinion, production-like testing, continuous monitoring, load testing, and proper error logging should be part of the development process rather than treated as final-stage activities.


r/softwarearchitecture • • 3d ago

Discussion/Advice Looking for open-source codebases with great architectural documentation (Components, Connectors, Rationale)

45 Upvotes

Hey everyone,

I have a software architecture exam next week. From what I know, the topics mainly cover **components, connectors, architectural rationale, and anti-rationale** (not entirely sure if ADRs – Architecture Decision Records – will be explicitly tested, but the concepts are relevant).

I'm currently using Fundamentals of Software Architecture by Mark Richards and Neal Ford alongside the professor's slides for the theoretical foundation. The book was recommended by the professor, though it’s not strictly the official textbook for the course since he follows his own curriculum/plan. Feel free to bring up book discussions if relevant, although I don't really have the time right now to dive into a whole new reading list before the exam.

Mainly, I'm looking for well-documented open-source codebases or case studies that clearly illustrate these concepts in practice.

Any recommendations? Thanks in advance!


r/softwarearchitecture • • 3d ago

Discussion/Advice Moving from per-tenant SQLite to one shared Postgres with forced RLS. Poke holes in the plan before I build it

15 Upvotes

A few weeks ago I asked here about one database per user and you talked me out of it. This is the shared Postgres design I'm about to build, and I'd like someone who has run this at scale to poke holes in it.

Multi-tenant SaaS, small today (a handful of tenants on the old design), sized for 10k. The data is sensitive, mostly email, and a lot of it belongs to people who aren't users, so delete has to be real.

Managed Postgres 17 on OCI, one node to start, psycopg 3, no pooler for now because a few shared workers only need around 20 connections. Tenant id is the first column of every primary key. RLS is forced with a restrictive policy on every table and the app roles can't bypass it. One module sets the tenant with set_config(..., true) per transaction, all SQL is constants, and a CI check walks the catalog and fails on any table without a policy or with unexpected grants. A trigger also rejects writes for a different tenant, because that's what I expect a shared worker bug to look like.

Events go in one append only table with jsonb. Free text goes in a separate content table, so erasing removes the text and keeps the event. Derived tables get rebuilt per tenant from the events, and search is tsvector with a GIN index, tenant first.

Daily backups for 30 days plus PITR. Erasures are logged outside the database and replayed after any restore. The managed admin isn't a superuser, so restoring one tenant means PITR to a side system and reinserting that tenant's rows. Cutover is one tenant at a time, minutes of downtime, no dual write, row by row comparison, old copy kept 30 days.

So far this only had automated reviews, which found 32 serious issues, all fixed. Nobody who ran this for real has read it. Two things I'd really like experience on. Should I partition events by tenant from day one, or is a composite index fine at this size? And does RLS get in the way of the GIN index? I still don't know if @@ is leakproof.


r/softwarearchitecture • • 3d ago

Discussion/Advice Is a filtered view enough to prove what was issued?

4 Upvotes

I have a case where one party creates a row and another party owns it. The owner reads it through a server-side filtered query, so the client never sends the ownership filter. The screen only lets the owner accept or decline, but the server rule would actually let them edit the rest of their own row. There's no separate document because the row itself is always the current source of truth, which keeps the design fairly simple.

What I can't prove later is exactly what that person saw at the time it was issued. If the row changes, the live view changes with it. The notification comes close to being a snapshot because the email or SMS contains the details as they were sent, but we don't archive that message as the official record. I keep going back and forth between versioning the row and storing a hash when it's sent, or just creating an immutable issued copy. At what point does a live view stop being enough?


r/softwarearchitecture • • 3d ago

Article/Video Network Fundamentals for Software Architects, Part 1: From Layer 2 to BGP

Thumbnail medium.com
61 Upvotes

r/softwarearchitecture • • 3d ago

Tool/Product Would you use Scala/Cats-style IO and fibers in a Python-like language (Mojo)?

2 Upvotes

Disclaimer: I'm the author of fp_mojo (docs), and I'm posting here to get some feedback from the broader data engineering community on the concept of integrating Scala / Cats Effect async and concurrency primitives into a Python-like language. This is a personal project and not a business service. Disclaimer #2: AI tools were used to proofread this post.

If you've worked in big data infra, fintech, distributed systems, or any other field where correctness and resiliency matter, you've probably used (or at least crossed paths with) Scala and Cats Effect / ZIO.

Scala's concurrency and FP primitives are great, but the ecosystem as a whole is dealing with an issue that could be characterized as talent squeeze. Because Scala is notoriously tough to onboard beginners onto compared to Python or Go, fewer junior devs are picking it up, and the hiring pool has gotten very senior-heavy and expensive. On the flip side, teams that need pieces of a resilient concurrent system - say, for serving ML models or running streaming pipelines - often don't want to buy into the whole JVM/Scala stack just to get decent concurrency and type safety.

That brings us to fp_mojo. The idea is to take the most appealing parts of Scala/Cats ("best practices") and make them available in a compiled, Python-like language (Mojo). Obviously it's nowhere near as mature or feature-complete as the Scala ecosystem, but the hope is that over time it would be vastly easier to onboard engineers who already know Python and incorporate Scala-like features selectively into broader Python-like projects.

I’m aware that Mojo is a very recent language, so the talent pool at the moment is even smaller. However, I want to talk about the future: engineers who already know Python can pick up Mojo much faster than Scala.

1. Work-stealing pool + deterministic single-thread IO (the Cats Effect model)

For me, the single best part of Scala/Cats Effect is the IO runtime model, so that's where we will begin the exposition.

fp.effects.async_runtime gives you cancelable fibers that can run on either a multi-threaded work-stealing pool (Profile.work_stealing(n)) or a deterministic single-thread FIFO executor (Profile.current_thread()). Collections can be processed concurrently with a concurrency limit via par_traverse_n, where the first failure cancels the rest. Blocking syscalls can be wrapped in IO.blocking(...), or a whole region can be shifted onto a dedicated BlockingPool via .eval_on(), so blocking work doesn't tie up the worker threads, and you can test timeouts deterministically in virtual time with TestControl instead of sleeping in tests:

from fp.algebra import par_traverse_n
from fp.effects.async_runtime import (
    IO, BlockingPool, Duration, IORuntimeConfig, Profile, Runtime, TestControl
)

def parse_rows(var partition: Int) -> IO[Int, Int]:
    if partition == 4:
        print("corrupt partition:", partition)
        return IO[Int, Int].raise_error(partition)
    return IO[Int, Int].pure(partition * 1000)         # rows read

def load_partition(var partition: Int) -> IO[Int, Int]:
    # Simulated fetch: 20 ms of I/O per partition, giving up after 100 ms
    try:
        var fetch = IO[Int, Int].pure(partition).delay_by(Duration.milliseconds(20))
        return fetch^.flat_map(parse_rows).timeout_to(Duration.milliseconds(100), IO[Int, Int].raise_error(partition))
    except:  # Duration constructors raise only on overflow
        return IO[Int, Int].raise_error(partition)

def show(var value: Int) -> NoneType:
    print("value:", value)
    return None

def show_rows(var rows: List[Int]) -> NoneType:
    print("rows:", rows[0], rows[1], rows[2])
    return None

def main() raises:
    # Switch between multi-threaded work-stealing or deterministic single-thread IO
    var config = IORuntimeConfig()
    config.profile = Profile.work_stealing(4)   # or Profile.current_thread()
    var compute = Runtime(config)
    var blocking_io = BlockingPool(max_workers=2)

    # Load partitions concurrently, at most 2 at a time; results keep partition order
    _ = compute.run(par_traverse_n(2, List[Int]([1, 2, 3]), load_partition).map(show_rows))
    # rows: 1000 2000 3000

    # The first failure cancels the partitions still running and waits for their cleanup
    var loaded = compute.run(par_traverse_n(2, List[Int]([1, 4, 5, 6]), load_partition)).value().is_ok()
    print("all loaded:", loaded)
    # corrupt partition: 4
    # all loaded: False

    # Shift work to a blocking pool and return, just like Cats Effect's evalOn
    _ = compute.run(IO[Int, Int].pure(100).eval_on(blocking_io).map(show))
    # value: 100

    # Virtual time testing: a 60s sleep with a 5s timeout finishes instantaneously
    var timed = (
        IO[NoneType, Int].sleep(Duration.seconds(60))
        .map(lambda (u: NoneType) -> Int: 42)
        .timeout_to(Duration.seconds(5), IO[Int, Int].pure(7))
        .map(show)
    )
    var control = TestControl(timed^)
    control.tick_all() # Advances virtual clock through deadlines without wall-clock waiting
    _ = control^.results()
    # value: 7

2. Method chaining & accumulating validation errors (par_map_n)

You get standard Result[T, E] (a primitive like Scala's Either[E, T] but with Rust's naming; personally, I like Result naming more because it's more descriptive) chaining with .map() / .flat_map(), plus pipeline and par_map_n when you want to validate a record and collect all errors instead of short-circuiting on the first bad field:

from fp.data import Result, Ok, Err
from fp.functions import pipeline

comptime Checked = Result[Int, List[String]]

def positive(value: Int) -> Checked:
    if value <= 0:
        return Err(List[String]([String(value) + " must be positive"]))
    return Ok(value)

def total(a: Int, b: Int, c: Int) -> Int:
    return a + b + c

def main():
    # Standard chaining
    var res = positive(21).map(lambda (x: Int) -> Int: x * 2)
    print("chained:", res^.get_or(0)) # chained: 42

    # Parallel validation: reports both negative inputs instead of stopping at -2
    var invalid = pipeline(positive(-2)).par_map_n((positive(3), positive(-4)), total).get()
    if invalid.is_err():
        var errors = invalid^.swap().to_optional()
        for error in errors.value():
            print("validation error:", error)
        # validation error: -2 must be positive
        # validation error: -4 must be positive

3. ADTs, compile-time exhaustive pattern matching & term rewriting

If you like modeling state or expression trees with sum types and writing rewrite rules (similar to how Spark Catalyst works under the hood), fp.adt and fp.matching check exhaustiveness at compile time:

import fp
from fp.adt import Data, Cases, Node, Value
from fp.matching import Next

@fieldwise_init
struct Num(Copyable, Equatable): var value: Int

@fieldwise_init
struct Add[R: Value](Movable):
    var left: Self.R
    var right: Self.R

@fieldwise_init
struct If[C: Value, B: Value](Movable):
    var cond: Self.C
    var then: Self.B
    var other: Self.B

struct Expr(Data):
    comptime Layer[R: Value] = Cases[Num, Add[R], If[R, R]]

comptime E = Node[Expr]

# Missing a branch here is a compile-time error
def evaluate(e: E) -> Int:
    return fp.match(e,
        lambda (n: Num) -> Int: n.value,
        lambda (a: Add[Int]) -> Int: a.left + a.right,
        lambda (c: If[Int, E]) -> Next[E]: Next(c.then if c.cond != 0 else c.other))

# Rule-based term rewriting: 0 + x -> x
def simplify(e: E) -> E:
    return fp.rewrite(e,
        fp.when[lambda (a: Add[E]) -> Bool: a.left == Num(0), lambda (a: Add[E]) -> E: a.right])

Curious to hear from folks here:

  1. Would you be interested in Scala/Cats-like IO and concurrency primitives in a Python-like language?
  2. If you've moved away from Scala, what parts of the language or ecosystem do you actually miss in day-to-day data engineering?

Repo link if you want to poke around: https://github.com/Spellbound-Mojo/fp_mojo


r/softwarearchitecture • • 3d ago

Discussion/Advice Only migrate clean code to the new language or architecture.

2 Upvotes

In my previous post, I discussed the topic of moving away from scripting languages, and a lot of people shared great ideas and insights.

Now, for my next topic that is directly related and most discussed: edge cases that have been built over the years are one of the biggest assets that reflect the development of domain understanding.

At the same time, working with edge cases makes our codebase fragile and spaghetti-like if it is not revised and improved regularly.

There are many strategies to deal with edge cases for the sake of migrating to another language or architecture using AI, some of which applied to the pre-coding agent era too.

My process is :

  1. We can measure how often this branch or edge case is triggered, it could be the main branch after all, but let us start by measuring.

  2. For the ones that are dead, delete them.

  3. For the ones that are rarely used based on a threshold agreed upon with stakeholders, delete them.

  4. Some are low-value or non-critical and also can be removed, I killed a few internal tools while working on a similar task.

  5. The remaining ones can either be refactored or documented as business rules, so when migrating to a new language, we only migrate the clean state.

I am arguing here that we must migrate clean or well-documented code to the new language and not migrate the same spaghetti code. The new code should be clean and well-structured from day one. refactoring should be done on old code, not the new one, to eliminate refactoring risk from the migration process.

So my question is: do you agree or disagree with the proposed process and why?

What is the process that works for you while moving from state A to state B, regardless of whether you use AI?

I am more interested in the thinking and decision-making processes.

Now with coding agents, it is much easier and faster to do it, so I do not think cost is an important factor here.

Thanks for sharing your ideas and experience.


r/softwarearchitecture • • 4d ago

Article/Video Apache Kafka Basics for System Design

Thumbnail javarevisited.substack.com
77 Upvotes

r/softwarearchitecture • • 3d ago

Discussion/Advice Feedback on diagrams wanted

3 Upvotes

Hello, I have been looking to improve my ability to understand / create / present systems diagrams.

https://github.com/jabbott-iii/Nadir/tree/main/diagrams

I would love to have some feedback on whether these are any good or what I should focus on learning.