Starlink bağlantısıyla uçan yeni polis dronu: 100 km/s ile araç kovalıyor
BRINC’in Starlink destekli yeni polis dronu Guardian, saatte 100 km hızla araç takip yapabiliyor. Dron, otomatik batarya değişimi sayesinde uzun süre görev yapabiliyor.
BRINC’in Starlink destekli yeni polis dronu Guardian, saatte 100 km hızla araç takip yapabiliyor. Dron, otomatik batarya değişimi sayesinde uzun süre görev yapabiliyor.
Avrupa Komisyonu ile ilişkili olan web platformlarına ve çalışanların veri tabanlarına sızan siber saldırganların devasa miktarlarda bir veriyi çaldıkları açıklandı.
ABD’li yetkililer, Çin’in en büyük çip üreticisi SMIC’in İran’ın askeri sanayisine ekipman ve teknik destek sağladığını öne sürdü. Bu iddialar küresel gerilimi daha da artırabilir. The Problem No One Talks About in the Microservices Hype
It’s 2019. Your team has just finished migrating a perfectly functional ASP.NET MVC app to microservices. You now have 14 services, a Kubernetes cluster, a service mesh, distributed tracing, a message broker, and three engineers whose full-time job is keeping it all running. Feature velocity? Cut in half. Onboarding a new developer? Two weeks just to understand the infrastructure.
Sound familiar?
The architecture community spent a decade evangelizing microservices as the solution to every scalability and maintainability problem. And while microservices genuinely solve hard problems at scale, they come with an enormous operational and cognitive tax — one that most product teams can’t afford, and frankly don’t need to pay.
Enter the Modular Monolith: not a retreat to the big ball of mud, and not the complexity of distributed systems. It’s an architectural style that enforces clear internal boundaries while keeping the simplicity of a single deployable unit. For many .NET teams, it’s the most pragmatic choice they never considered.
What Is a Modular Monolith?
A modular monolith is a single deployable application composed of well-defined, loosely coupled internal modules, each owning its own domain logic, data, and public API surface.
The key distinction from a traditional monolith is intentional structure. A classic monolith tends to evolve into spaghetti — shared database tables, cross-cutting service dependencies, and no clear ownership boundaries. A modular monolith fights this entropy from day one by treating each module as if it were a microservice candidate, without actually making it one yet.
The Three-Way Comparison:
| Dimension | Traditional Monolith | Modular Monolith | Microservices |
|---|---|---|---|
| Deployment | Single unit | Single unit | Multiple units |
| Module boundaries | Weak / absent | Strong, enforced | Strong, enforced |
| Data isolation | Shared DB | Logical isolation | Physical isolation |
| Communication | Direct calls | In-process events | Network (HTTP/gRPC/MQ) |
| Operational complexity | Low | Low | High |
| Refactoring cost | High (tightly coupled) | Medium | High (distributed) |
| Team autonomy | Low | Medium | High |
| Latency overhead | None | None | Network latency |
Think of it this way: a modular monolith is a microservices architecture collapsed into a single process. The boundaries are real — they’re just not physical.
Why Not Just Use Microservices?
Microservices are genuinely powerful when you need:
But the prerequisites are steep. You need mature DevOps culture, a platform team, distributed tracing, eventual consistency patterns, saga orchestration, and more. The distributed fallacies (network is reliable, latency is zero, bandwidth is infinite…) become your daily enemies.
The hidden costs of premature microservices decomposition:
A modular monolith defers these costs until they’re actually justified. And for many applications — even those at serious scale — that day may never come.
Core Principles
1. Module Boundaries
A module is a cohesive grouping of functionality around a bounded context (to borrow DDD terminology). In an e-commerce system, natural modules might be Orders, Catalog, Users, Payments, and Notifications.
The boundary rule is simple: modules do not reference each other’s internals. If Orders needs a product name, it doesn’t call Catalog‘s internal ProductService — it goes through a defined public contract.
2. High Cohesion / Low Coupling
Everything related to the Catalog domain lives inside Catalog: its entities, repositories, domain services, use cases, and event handlers. Nothing leaks out. Other modules don’t know Catalog has an EfCore repository — they only know the public interface it exposes.
3. Independent Data Per Module
This is the most important and most violated principle. Each module should own its own data. In a modular monolith, you typically use a single database with schema-level separation (e.g., catalog.Products, orders.Orders), or separate DbContext instances that map to different schemas.
No module queries another module’s tables directly. Ever. This is the line between a modular monolith and a well-organized big ball of mud.
4. Communication Patterns
Modules communicate in two ways:
Synchronous (in-process): One module exposes an interface (e.g., ICatalogModule) and another calls it through the DI container. This is appropriate for read queries where you need an immediate result.
Asynchronous (domain events): When Orders places an order, it publishes an OrderPlacedEvent. Inventory and Notifications handle it independently. This is done in-process using a mediator or event dispatcher — no message broker required.
Implementing in .NET
Project Structure
src/
├── ECommerce.Api/ # Host project (entry point)
│ ├── Program.cs
│ └── appsettings.json
│
├── ECommerce.Shared/ # Cross-cutting contracts
│ ├── Events/ # Domain event interfaces
│ └── Modules/ # IModule interface
│
├── ECommerce.Modules.Catalog/ # Catalog module (Class Library)
│ ├── CatalogModule.cs # Module registration
│ ├── Domain/
│ │ └── Product.cs
│ ├── Application/
│ │ ├── GetProductQuery.cs
│ │ └── GetProductQueryHandler.cs
│ ├── Infrastructure/
│ │ ├── CatalogDbContext.cs
│ │ └── ProductRepository.cs
│ └── Api/
│ └── CatalogEndpoints.cs
│
├── ECommerce.Modules.Orders/ # Orders module (Class Library)
│ ├── OrdersModule.cs
│ ├── Domain/
│ │ └── Order.cs
│ ├── Application/
│ │ ├── PlaceOrderCommand.cs
│ │ └── PlaceOrderCommandHandler.cs
│ ├── Infrastructure/
│ │ └── OrdersDbContext.cs
│ └── Api/
│ └── OrdersEndpoints.cs
│
└── ECommerce.Modules.Users/ # Users module (Class Library)
Each module is a separate class library project. The Api host project references all modules, but modules reference only ECommerce.Shared — never each other directly.
The IModule Contract
Define a shared registration interface that every module implements:
// ECommerce.Shared/Modules/IModule.cs
public interface IModule
{
string Name { get; }
IServiceCollection RegisterServices(
IServiceCollection services,
IConfiguration configuration);
WebApplication MapEndpoints(WebApplication app);
}
Module Registration in Program.cs
// ECommerce.Api/Program.cs
var builder = WebApplication.CreateBuilder(args);
// Each module self-registers
var modules = new IModule[]
{
new CatalogModule(),
new OrdersModule(),
new UsersModule(),
};
foreach (var module in modules)
module.RegisterServices(builder.Services, builder.Configuration);
builder.Services.AddMediatR(cfg =>
cfg.RegisterServicesFromAssemblies(
typeof(CatalogModule).Assembly,
typeof(OrdersModule).Assembly,
typeof(UsersModule).Assembly));
var app = builder.Build();
foreach (var module in modules)
module.MapEndpoints(app);
app.Run();
DI Per Module
Each module’s RegisterServices method wires up its own dependencies in isolation:
// ECommerce.Modules.Catalog/CatalogModule.cs
public class CatalogModule : IModule
{
public string Name => "Catalog";
public IServiceCollection RegisterServices(
IServiceCollection services,
IConfiguration configuration)
{
services.AddDbContext<CatalogDbContext>(opts =>
opts.UseSqlServer(
configuration.GetConnectionString("Catalog"),
sql => sql.MigrationsHistoryTable("__EFMigrationsHistory", "catalog")));
services.AddScoped<IProductRepository, ProductRepository>();
services.AddScoped<ICatalogModule, CatalogModuleFacade>();
return services;
}
public WebApplication MapEndpoints(WebApplication app)
{
app.MapGroup("/catalog").MapCatalogEndpoints();
return app;
}
}
Real-World Example: E-Commerce Order Placement
Let’s trace an order placement flow across modules.
The Cross-Module Contract
Orders needs to verify product prices from Catalog. It does this through a public facade interface — not by importing Catalog‘s internal types:
// ECommerce.Shared/Modules/ICatalogModule.cs
public interface ICatalogModule
{
Task<ProductDto?> GetProductAsync(Guid productId);
}
public record ProductDto(Guid Id, string Name, decimal Price, bool IsAvailable);
Placing an Order
// ECommerce.Modules.Orders/Application/PlaceOrderCommandHandler.cs
public class PlaceOrderCommandHandler
: IRequestHandler<PlaceOrderCommand, Guid>
{
private readonly IOrderRepository _orders;
private readonly ICatalogModule _catalog; // cross-module contract
private readonly IPublisher _publisher; // MediatR publisher
public PlaceOrderCommandHandler(
IOrderRepository orders,
ICatalogModule catalog,
IPublisher publisher)
{
_orders = orders;
_catalog = catalog;
_publisher = publisher;
}
public async Task<Guid> Handle(
PlaceOrderCommand command,
CancellationToken cancellationToken)
{
var product = await _catalog.GetProductAsync(command.ProductId);
if (product is null || !product.IsAvailable)
throw new DomainException("Product not available.");
var order = Order.Create(command.CustomerId, product.Id, product.Price);
await _orders.AddAsync(order, cancellationToken);
// Publish domain event — handled by other modules in-process
await _publisher.Publish(
new OrderPlacedEvent(order.Id, product.Id, command.CustomerId),
cancellationToken);
return order.Id;
}
}
Handling the Event in Another Module
// ECommerce.Modules.Notifications/Application/SendOrderConfirmationHandler.cs
public class SendOrderConfirmationHandler
: INotificationHandler<OrderPlacedEvent>
{
private readonly IEmailService _email;
private readonly IUsersModule _users;
public async Task Handle(
OrderPlacedEvent notification,
CancellationToken cancellationToken)
{
var user = await _users.GetUserAsync(notification.CustomerId);
await _email.SendOrderConfirmationAsync(user.Email, notification.OrderId);
}
}
Orders publishes an event. Notifications handles it. Neither knows the other exists. This is the power of in-process messaging with MediatR — you get the decoupling benefits of a message bus without the operational overhead.
Common Pitfalls
1. The Shared Database Anti-Pattern
The most common failure mode: all modules share a single DbContext and freely query each other’s tables. You end up with JOINs across module boundaries, and suddenly changing a column in catalog.Products breaks 4 other modules.
The fix: One DbContext per module, separate DB schemas, zero cross-schema queries. If module B needs data from module A, it calls A’s public API — not its tables.
2. Tight Coupling Through Shared Domain Models
Referencing another module’s domain entities directly creates invisible coupling. If Orders imports Catalog.Domain.Product, you’ve created a compile-time dependency that defeats the entire architecture.
The fix: Shared contracts live in ECommerce.Shared as DTOs or interfaces. Domain models are private to their module.
3. Overengineering Small Applications
If your application is a CRUD API with 5 entities and no meaningful domain complexity, a modular monolith is overkill. You’re adding project structure, DI ceremony, and module facades for no real benefit.
The fix: Apply this architecture when you have genuine domain complexity, multiple teams, or a realistic expectation of growth. Don’t architect for hypothetical futures.
When to Choose Modular Monolith vs. Microservices
Choose a Modular Monolith when:
Choose Microservices when:
The honest truth: Most applications should start as a modular monolith. If they grow to need microservices, the modular structure makes extraction far less painful than it would be from a traditional monolith.
Scaling and Evolution Strategy
One of the strongest arguments for this architecture is its evolutionary path. Because your modules already have clean boundaries, migrating a single module to a standalone service is a surgical operation, not a rewrite.
The extraction checklist for a module:
DbContext and schema — point it at a separate databaseIPublisher to publishing to a message broker (e.g., MassTransit + RabbitMQ)In practice, extraction of a well-bounded module can take days, not months. Compare this to extracting from a traditional monolith where untangling shared state, circular dependencies, and cross-table queries can take quarters.
A practical evolution path looks like this:
Phase 1: Modular Monolith (single deployment, all modules)
↓ (Catalog service gets high read traffic)
Phase 2: Extract Catalog to a standalone service
→ Orders calls Catalog via HTTP
→ Events go through a message broker
↓ (Payments needs PCI compliance isolation)
Phase 3: Extract Payments to a standalone service
→ Now you have 3 deployable units
You scale surgically, not speculatively.
Key Takeaways
DbContext instances, public facade interfaces in a shared contracts project, and MediatR for in-process event-driven communicationThe architecture world likes clean, binary choices. Microservices or monolith. Distributed or single process. But the most pragmatic choice is often in the middle: a system that’s well-structured enough to evolve, and simple enough to actually ship.
Have you migrated to or from a modular monolith? The edge cases are always where the real lessons live — reach out or drop a comment.
I built a CLI that diagnoses your code before you ship
Every NestJS project I’ve worked on had the same problems:
POST endpoints without auth guards
Hardcoded API keys in source code
.env not in .gitignore
Zero tests
No Swagger documentation
I was tired of catching these manually in code reviews. So I built codediag.
What it does
bashnpx codediag scan .
One command. It auto-detects your stack and runs 5 analyzers:
codediag — Diagnostic Report
Project: my-nestjs-app
Stack: nestjs + typescript + prisma
Score: B+ (87/100)
API Health ███████████████░░░░░ 78
Security ██████████████████░░ 92
Dependencies ██████████████████░░ 91
Testing ████████████████░░░░ 82
Structure █████████████████░░░ 88
The 5 Analyzers
Auth guards: Does this endpoint have @UseGuards()? Especially important for mutating endpoints.
DTO validation: Is the @body() parameter typed with a DTO class?
Swagger docs: Are @ApiOperation() and @ApiResponse() present?
Return types: Is there an explicit return type annotation?
Hardcoded secrets (API keys, Stripe keys, AWS keys, GitHub tokens)
.env in .gitignore
Helmet middleware for HTTP security headers
CORS wildcard (origin: ‘*’) detection
Rate limiting package installed
Password hashing library present
npm audit vulnerabilities
Lock file existence
Deprecated packages
Engine specification
Essential scripts
Test file existence and count
Framework detection (Jest, Vitest, Mocha, Ava)
Test-to-source file ratio
E2E test directory
Coverage threshold configuration
README quality
Linter configuration (ESLint or Biome)
Formatter configuration (Prettier)
TypeScript strict mode
NestJS module organization
.env.example presence
Scoring
Each analyzer scores 0-100. The total is a weighted average:
AnalyzerWeightAPI Health25%Security30%Dependencies20%Testing15%Structure10%
Security gets the highest weight because shipping vulnerable code is the worst bug.
CI/CD
One line in your GitHub Actions:
yaml- run: npx codediag scan . –ci –threshold 80
Exits with code 1 if the score drops below your threshold.
What’s next
Next.js analyzer
Express route analyzer
Web dashboard with trend tracking
AI-powered fix suggestions
VS Code extension
Try it
bashnpx codediag scan .
Zero config. MIT licensed. 33KB bundled.
GitHub: https://github.com/scuton-technology/codediag
npm: https://www.npmjs.com/package/codediag
I’d love to hear what checks you’d want added. Drop a comment or open an issue!
Argo CD and AWS CodeConnections: The Upside, the Redeploy Pain, and How I Fixed It
I run Argo CD on Amazon EKS using the managed Argo CD capability and AWS CodeConnections for Git. CodeConnections has been a clear win for day-to-day operations. Then I had to recreate the connection (new resource, new identity in the URL). Every Application went to Sync: Unknown until I updated URLs in two places—Git and the live cluster—and fixed ApplicationSets so they stopped writing the old URL back. This article leads with why I still choose CodeConnections, then what breaks on redeploy, then what I did when it inevitably happened, in that order.
1. Why CodeConnections is worth it for Argo CD on EKS
No SSH keys or personal tokens in the cluster. Argo pulls Git using IAM: the capability role is allowed to use the connection (UseConnection, GetConnection). You are not copying PATs into Secrets or rotating leaked keys because someone printed kubectl get secret.
One connection, many repos. The HTTPS URL includes your account, region, a connection UUID, and then owner/repo. Same connection, different path segment for each repository. Setup details and Terraform patterns are in Argo CD on EKS: Git repo access with AWS CodeConnections and Terraform.
Fits how enterprises already govern access. Connections are AWS resources; approval and auditing live next to the rest of your cloud controls.
That does not mean zero tradeoffs. Managed Argo CD often applies one Git credential broadly (for example every github.com fetch through Kustomize can inherit it). If that bites you, vendoring or URL strategy fixes it—see Why Your Kustomize Remote Bases Break on Managed Argo CD (and How to Fix It). The tradeoff this article focuses on is different: replacing the connection.
2. What actually hurts when you update or redeploy the connection
The Git URL Argo uses is not abstract. It embeds a connection UUID in the path. A new connection is a new UUID. Anything that still points at the old path keeps asking AWS to authorize the wrong resource, so repo fetch fails and sync never reconciles.
Pain point one — Git only is not enough. Your GitOps repo is the source of truth, but Kubernetes already has Application and ApplicationSet objects applied yesterday. Their spec.source.repoURL (and generator URLs on sets) stay on the old string until something updates them. Pushing Git does not retroactively patch those CRs.
Pain point two — ApplicationSets fight you. Many sets declare repoURL twice: on the git generator and again on the template. If you patch child Applications but leave the set on the old URL, the controller reconciles and puts the old URL back on the apps.
Pain point three — Terraform layout. If CodeConnections and the EKS cluster share one tangled module and state, recreating the connection can feel like you are planning half the platform when you only wanted a new Git pipe. I now prefer the connection (and its IAM attachment) in something standalone, with outputs the cluster stack consumes—so the next rotation is a smaller blast radius.
What this is not. If Argo shows forbidden listing some API group (for example heavy CRD surfaces from controllers like ACK), that is usually cluster RBAC / EKS access policies for the Argo identity, not the CodeConnections URL. Fix that on its own; do not confuse it with a UUID swap.
Do not mass-delete Applications to “fix” a bad URL. Workloads may still be fine; you risk prune tearing down real resources. Fix the URLs.
3. Prerequisites
kubectl against the cluster, with permission to read and patch applications and applicationsets in the Argo CD namespace (below I use argocd, the usual default) 4. If it happens to you: what worked for me
These steps assume you already know the old and new connection UUID (search your shell history, Terraform state, or an old Application YAML). The host pattern is documented in the CodeConnections and EKS guides linked at the end.
Step A — Fix Git first, everywhere
Search across all repos that participate in GitOps—not only the “main” infra repo:
rg 'codeconnections.' --glob '*.yaml' --glob '*.yml' --glob '*.tf' --glob '*.md'
Update bootstrap Application manifests, every ApplicationSet generator and template repoURL, any child Application checked in with a literal URL, and docs or scripts that build repository secrets. Commit and push.
Step B — Patch Applications in the cluster
Still in a broken state, the cluster cannot always sync from Git, so you patch live objects once. Set shell variables to your real values (namespace if not argocd, old UUID, new UUID):
NS=argocd
OLD_UUID=aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee
NEW_UUID=ffffffff-eeee-dddd-cccc-bbbbbbbbbbbb
List apps whose single spec.source.repoURL still contains the old UUID:
kubectl get applications -n "$NS" -o json | jq -r --arg u "$OLD_UUID"
'.items[] | select(.spec.source.repoURL // "" | contains($u)) | .metadata.name'
For each name, the safest approach is to take the existing URL from the object and swap the UUID in the shell, then merge-patch:
app=my-app
oldurl=$(kubectl get application "$app" -n "$NS" -o jsonpath='{.spec.source.repoURL}')
newurl="${oldurl//$OLD_UUID/$NEW_UUID}"
kubectl patch application "$app" -n "$NS" --type merge -p "{"spec":{"source":{"repoURL":"$newurl"}}}"
If you use spec.sources (multi-source), repeat the idea per entry that points at CodeConnections.
Step C — Patch ApplicationSets (do not skip this)
Confirm the old UUID still appears on spec (ignore status for a moment):
kubectl get applicationsets -n "$NS" -o yaml | rg "$OLD_UUID"
To replace the UUID everywhere under each set’s JSON (review before you run this in production—I exported one set first and eyeballed it):
for name in $(kubectl get applicationsets -n "$NS" -o json | jq -r --arg u "$OLD_UUID"
'.items[] | select(.. | strings? | contains($u)) | .metadata.name' | sort -u); do
kubectl get applicationset "$name" -n "$NS" -o json |
jq --arg o "$OLD_UUID" --arg n "$NEW_UUID"
'del(.status) | walk(if type == "string" then gsub($o; $n) else . end)' |
kubectl replace -f -
done
The walk replaces every occurrence of the old UUID string in that JSON. Pick a UUID substring unique to the connection so you do not hit unrelated fields.
Step D — Refresh and converge
Hard refresh apps in the UI or CLI, then let GitOps catch up. If Git still cannot be fetched until one app is fixed, patch your bootstrap Application (the one that applies the rest of the tree) to the new URL first, then repeat the rest—classic chicken-and-egg.
5. Troubleshooting
Application stuck deleting
kubectl patch application my-app -n argocd -p '{"metadata":{"finalizers":null}}' --type=merge
I deleted an app and it came back
An ApplicationSet owns it (ownerReferences). Fix the set and Git; deleting the app alone will not stick.
6. References
Heroku charges $25/mo for one hobby dyno. Dokku gives you unlimited apps on a $5 VPS with the same git push workflow.
What Is Dokku?
Dokku is the smallest PaaS implementation you’ve ever seen. It’s an open-source Heroku alternative that runs on any Linux server.
# Install on your VPS (Ubuntu)
wget -NP . https://dokku.com/install/v0.34.x/bootstrap.sh
sudo DOKKU_TAG=v0.34.8 bash bootstrap.sh
The Heroku Workflow
# On your server
dokku apps:create my-app
# On your local machine
git remote add dokku [email protected]:my-app
git push dokku main
That’s it. Dokku detects your language (Node, Python, Go, Ruby, etc.), builds it, and deploys it. Same buildpacks as Heroku.
Configuration
# Environment variables
dokku config:set my-app DATABASE_URL=postgres://...
dokku config:set my-app SECRET_KEY=my-secret
# Domains
dokku domains:add my-app myapp.com
dokku domains:add my-app www.myapp.com
# SSL (automatic Let's Encrypt)
dokku letsencrypt:enable my-app
# Scale
dokku ps:scale my-app web=2 worker=1
# Databases
dokku postgres:create mydb
dokku postgres:link mydb my-app
# DATABASE_URL is automatically set
Plugins for Everything
# PostgreSQL
dokku plugin:install https://github.com/dokku/dokku-postgres.git
# Redis
dokku plugin:install https://github.com/dokku/dokku-redis.git
# MySQL
dokku plugin:install https://github.com/dokku/dokku-mysql.git
# Let's Encrypt
dokku plugin:install https://github.com/dokku/dokku-letsencrypt.git
Cost Comparison
| Setup | Monthly Cost | Apps |
|---|---|---|
| Heroku | $25/app | 1 |
| Dokku on DigitalOcean | $5 total | Unlimited |
| Dokku on Hetzner | $4 total | Unlimited |
| Railway | $5/app | 1 |
A $5 VPS with 1GB RAM can run 3-5 small web apps with databases. A $12 VPS with 2GB handles 10+.
Why Dokku
Building deployment infrastructure? Check out my developer tools or email [email protected].
The first thing I wanted to focus on when I started to explore the Wagtail Starter kit was: how well is the starter kit able to help out someone building a real website for the first time?
To understand this, I set up the Wagtail starter kit locally and began studying how its pages, content blocks and templates were organized.
One of the first things I noticed was that Wagtail’s page-based structure is powerful but it takes a little time to understand. Wagtail treats content as different page types, each with its own role. That means understanding the site structure is just as important as understanding the code.
As I explored the starter, I began mapping out the purpose of the main page types like-
Home page → landing page of the site
Standard page → generic content like About
Form page → pages like Contact
This helped me see that one of Wagtail’s biggest strengths is structured content. Once the page hierarchy is clear, the editing experience becomes much more easier.
To understand the starter more deeply, I adapted it into a beginner-friendly blog structure. I explored improvements such as-
This made me realize that the biggest improvements to a starter kit are not always “big features.” Often, they are small usability improvements that reduce confusion and help new users feel confident.
My biggest learning after exploring the Wagtail starter kit is this-
A good starter should not just run, it should also teach the most important aspects.
This is what makes starter kits essential, especially for beginners.
Exploring the Wagtail starter kit gave me a much better understanding of how Wagtail balances developer flexibility with editor experience and it also gave me a clearer direction for what I would like to improve further.
What if Python was 68,000x faster? Not a typo. Mojo achieves C/C++ performance with Python syntax.
What Is Mojo?
Mojo is a programming language that’s a superset of Python — your existing Python code runs in Mojo — but adds systems programming features that make it as fast as C.
# This is valid Mojo AND valid Python
def hello():
print("Hello from Mojo!")
# But Mojo adds performance features
fn fast_hello():
print("Hello from fast Mojo!")
def works like Python (dynamic). fn is Mojo-specific (static, fast).
The Performance
# Mojo struct with SIMD operations
struct Matrix:
var data: DTypePointer[DType.float64]
var rows: Int
var cols: Int
fn __init__(inout self, rows: Int, cols: Int):
self.rows = rows
self.cols = cols
self.data = DTypePointer[DType.float64].alloc(rows * cols)
fn matmul(self, other: Matrix) -> Matrix:
var result = Matrix(self.rows, other.cols)
@parameter
fn calc_row(i: Int):
for j in range(other.cols):
var sum: Float64 = 0
@parameter
fn dot[simd_width: Int](k: Int):
sum += (self.data.load<a href="i * self.cols + k">width=simd_width</a> *
other.data.load<a href="k * other.cols + j">width=simd_width</a>).reduce_add()
vectorize[dot, simdwidthof[DType.float64]()](self.cols)
result.data.store(i * other.cols + j, sum)
parallelize[calc_row](self.rows)
return result
Auto-vectorization + parallelization in a Python-like language. This runs at C speed.
Python Compatibility
# Import any Python library
from python import Python
def use_numpy():
np = Python.import_module("numpy")
arr = np.array([1, 2, 3, 4, 5])
print(np.mean(arr)) # Works!
plt = Python.import_module("matplotlib.pyplot")
plt.plot(arr)
plt.show()
All of PyPI works. NumPy, Pandas, TensorFlow, PyTorch — import and use them.
Why Mojo
Building high-performance AI systems? Check out my developer tools or email [email protected].
We built Respiro because of a question: what if your phone could notice you’re stressed before you do?
Turns out, it can. Without a smartwatch. Without asking you to check in. Just by listening to the signals your phone already collects.
The 29 Signals
Your iPhone generates data constantly. Most apps ignore it. We don’t.
Here’s what we read:
From motion sensors (accelerometer + gyroscope):
From usage patterns:
From health data (with permission):
From context:
From environmental signals:
Why 29 Signals Instead of 1?
A single metric lies. Heart rate spikes when you climb stairs, not just when you’re stressed. HRV drops when you’re dehydrated.
But when your typing speed increases AND your screen unlocks jump AND your calendar is packed AND your HRV dropped — that’s a pattern. That’s stress.
We use on-device ML to weigh these signals together. No data leaves your phone. No cloud processing. Your stress data stays yours.
What Happens When Stress Is Detected
This is where most apps would say “take a deep breath.” We do something different.
We match the intervention to the moment:
The intervention library has 34 practices across breathing, body, mind, and emergency categories. Each backed by peer-reviewed research.
The Counterintuitive Finding
When we tested this internally, the most common reaction was: “I didn’t know I was stressed.”
Not “this breathing exercise is great.” Not “cool app.”
Just: “I thought that’s how Tuesdays feel.”
Turns out, chronic stress becomes invisible. Your baseline shifts so gradually that exhaustion feels normal. The value isn’t the breathing exercise — it’s the awareness that you needed one.
The Technical Bet
We’re betting that passive detection beats active check-ins. Every wellness app asks you “how do you feel?” — and every user lies or forgets or stops opening the app after week 2.
Respiro never asks. It watches the signals, does the math on-device, and shows up with the right practice at the right moment. 30 seconds, not 30 minutes.
If you’re curious about the technical architecture or want to try it yourself — it’s free to download on iOS.
What We Learned Building This
Consistency > technique > duration. A 2026 UCSF study (n=1,458) confirmed: daily 5-min practice outperforms sporadic 20-min sessions across ALL modalities. The best breathing exercise is the one you actually do.
Cyclic sighing wins. Stanford tracked 111 people. 5 minutes of cyclic sighing daily beat mindfulness meditation on every anxiety measure (Balban et al., Cell Reports Medicine, 2023).
On-device ML is non-negotiable. Users who heard “your stress data goes to the cloud” said no. Every single one. Privacy isn’t a feature — it’s a prerequisite.
The phone knows more than the wearable. Apple Watch gives you heart rate. Your phone gives you behavior patterns. Behavior changes before biology does — you check your phone more before your heart rate rises.
Respiro detects stress from your phone’s sensors — no wearable needed. Try it free.