Sr. Content Developer at Microsoft, working remotely in PA, TechBash conference organizer, former Microsoft MVP, Husband, Dad and Geek.
159429 stories
·
33 followers

Why BlocSignal Doesn't Need Provider (And Why Classic BLoC Always Did)

1 Share

How shedding package:provider eliminates dependency hell, fixes Flutter's lingering ghost rebuild bug, and delivers fine-grained synchronous reactivity in 2026.

If you browse r/FlutterDev on any given week, you will find the exact same architectural debate playing out:

"Should I use BLoC or Riverpod for my next production app? BLoC has great structure and discipline, but the stream boilerplate is overwhelming. Riverpod is reactive and flexible, but the @riverpod code generation and constant version transitions make it feel heavyweight."

And inevitably, someone in the comments will chime in:

"I just stick with plain package:provider because it's simple and doesn't require code-gen."

This trilemma—BLoC vs. Riverpod vs. Provider—has defined Flutter state management for over six years. But behind this debate lies a little-known architectural secret that explains why Flutter state management felt so fractured in the first place:

Classic flutter_bloc was secretly just package:provider in disguise.

Let's look at why classic BLoC relied on package:provider, the hidden runtime bugs and dependency deadlocks that came with it, why Riverpod had to break away, and how BlocSignal delivers the ultimate resolution: zero provider, zero streams, and zero code generation.

1. Look Under the Hood: Classic BLoC's Hidden Dependency

When developers think of Felix Angelov’s classic flutter_bloc, they think of Streams, Sinks, and unidirectional event architectures. But if you open flutter_bloc/pubspec.yaml, you'll find a foundational dependency:

dependencies:
  bloc: ^8.1.4
  provider: ^6.0.5 # 👈 The hidden foundation!

In classic flutter_bloc:

  • BlocProvider<T> is literally an extension of package:provider's InheritedProvider.
  • MultiBlocProvider is just a thin alias over MultiProvider.
  • RepositoryProvider is literally Provider<T>.

Why Did Classic BLoC Do This?

Back in 2018–2019, writing custom InheritedWidget plumbing in Flutter was verbose and error-prone. Rémi Rousselet’s package:provider was the newly crowned Google-recommended solution for dependency injection and widget tree scoping.

Building flutter_bloc on top of package:provider allowed BLoC to focus on its stream state machine while outsourcing widget tree scoping, lazy instantiation, and disposal to Provider.

It seemed like a great shortcut. But over time, coupling BLoC to package:provider introduced two massive architectural headaches.

2. The Two Fatal Flaws of the Provider Foundation

[ Your Application ] ──► [ flutter_bloc ]
                            │
                            └──► [ package:provider ] ──► [ Transitive Version Lock ]

Flaw #1: "Dependency Hell" & Version Lockouts

Because package:provider is one of the most widely used packages in the Flutter ecosystem, major version updates (such as migrating from v4 to v5 to v6 for null safety) created widespread dependency deadlocks:

Because my_app depends on:
  - legacy_auth_plugin ^2.1.0 (which depends on provider ^5.0.0)
  - flutter_bloc ^8.0.0 (which depends on provider ^6.0.5)

Version solving failed:
Cannot solve dependencies because provider ^5.0.0 is incompatible with provider ^6.0.5!

Every Flutter developer has experienced this nightmare:

  • You couldn't upgrade flutter_bloc because an analytics or payment SDK pinned an older provider.
  • Teams were forced to use risky dependency_overrides: in pubspec.yaml and pray that internal breaking changes wouldn't crash production builds.
  • Engineers had to fork third-party repositories just to bump a provider constraint.

Flaw #2: The "Lingering Dependency" (Ghost Rebuild) Bug

This is the deepest, most subtle flaw in Flutter's InheritedWidget system—and it was the primary catalyst that drove Rémi Rousselet to abandon Provider and create Riverpod.

When an Element calls context.watch<T>() or Provider.of<T>(context), Flutter registers that Element as a dependent of the ancestor InheritedWidget.

The fatal catch: Flutter’s engine never unregisters an element from an InheritedWidget on subsequent builds! Dependencies are only cleared when the widget is completely unmounted.

Consider this common conditional UI pattern:

// 👴 The Classic Provider Ghost Rebuild Trap:
Widget build(BuildContext context) {
  if (isExpanded) {
    // 🚩 Registers a permanent dependency on DetailsModel
    final details = Provider.of<DetailsModel>(context);
    return FullDetailsCard(details);
  } else {
    // 👻 GHOST REBUILD: Even when collapsed, this widget STILL rebuilds 
    // on every single change to DetailsModel forever!
    return const CompactSummaryCard();
  }
}

Once isExpanded is true even once, Flutter permanently binds DetailsModel to that widget. When the card collapses, it continues to rebuild on every DetailsModel emission indefinitely, wasting CPU cycles, battery, and rendering frames on state it isn't even displaying!

3. The Riverpod Exodus: Escaping the Widget Tree

Rémi recognized that Flutter's InheritedWidget and BuildContext had fundamental limitations that could not be fixed within package:provider:

  1. You couldn't easily read state outside the widget tree (for example, in background services or pure Dart logic).
  2. The lingering dependency bug caused unavoidable ghost rebuilds on conditional branches.
  3. Combining two providers required ugly nested widget hierarchies or manual proxies.

So Rémi built Riverpod (ProviderContainer), moving the entire dependency and state graph outside of the Flutter widget tree.

Where Riverpod Got Complicated

While Riverpod solved the BuildContext coupling, it created a new set of challenges:

  • The @riverpod Code-Gen Dogmatism: To avoid writing boilerplate notifiers, developers were pushed toward build_runner and code generation. If you didn't run a file watcher in the background, development ground to a halt.
  • Complex Internal Types: Behind a simple provider was a labyrinth of generated classes (AutoDisposeAsyncNotifierProviderElement, ProviderFamily, AsyncValue edge cases).
  • Two-World Impedance: Managing state in an external container while rendering in Flutter's Element tree required complex retention counters (autoDispose, disposeDelay, cacheTime) to guess when widgets were truly done using state.

4. The BlocSignal Resolution: Zero Provider, Zero Code-Gen

┌────────────────────────────────────────────────────────────────────────┐
│                              BlocSignal                                │
│                                                                        │
│   ┌────────────────────────┐              ┌────────────────────────┐   │
│   │   The Rigor of BLoC    │              │  The Speed of Signals  │   │
│   │  • Unidirectional flow │              │  • Synchronous DAG     │   │
│   │  • Explicit Events     │      ➕      │  • Dynamic Pruning     │   │
│   │  • Strict Transitions  │              │  • Zero Streams        │   │
│   │  • 100% Traceability   │              │  • Zero Code-Gen       │   │
│   └────────────────────────┘              └────────────────────────┘   │
└────────────────────────────────────────────────────────────────────────┘

BlocSignal resolves this historical progression by rethinking the state primitive from the ground up:

1. Native O(1) InheritedWidget (Zero Third-Party Dependencies)

In bloc_signals_flutter, BlocSignalProvider does not depend on package:provider.

  • It is built directly on Flutter's core SDK InheritedWidget.
  • It performs instant O(1) lookups via getElementForInheritedWidgetOfExactType without intermediate proxy nodes or delegating elements.
  • It has zero external dependencies—eliminating pub get version deadlocks permanently.

2. Dynamic Per-Frame Dependency Pruning (No Ghost Rebuilds)

Because BlocSignal is powered by fine-grained Signals (signals_flutter), dependencies are tracked dynamically on every single evaluation frame:

// ⚡ In BlocSignal: Zero Ghost Rebuilds!
Widget build(BuildContext context) {
  return Watch((context) {
    if (isExpanded.value) {
      // ✅ Subscribes to detailsCubit in this frame
      return FullDetailsCard(detailsCubit.state.value);
    }
    // ✅ When false, detailsCubit is AUTOMATICALLY UNWATCHED and detached!
    return const CompactSummaryCard();
  });
}

When isExpanded turns false, detailsCubit is immediately pruned and unwatched. If detailsCubit mutates while the card is collapsed, zero rebuilds occur. You get pristine, leak-free reactivity without code generation or external containers.

3. Synchronous State Propagation (No Stream Queue Latency)

Classic BLoC emits state over Dart asynchronous microtask Streams. Every state change yields to the event loop before reaching the screen.

In BlocSignal:

  • Calling emit(newState) updates the underlying ReadonlySignal<State> synchronously in the exact same frame.
  • The GPU and widget tree render the new state with zero microtask queue hops and zero 1-frame loading flickers.

4. Streamless BLoC-to-BLoC Coordination

In classic BLoC, coordinating two Blocs requires nesting BlocListener widgets in the UI tree or writing complex Rx stream pipelines.

In BlocSignal, because state is a Signal, containers can observe each other directly in pure business logic:

class CartCubit extends CubitSignal<CartState> {
  CartCubit(this.authCubit) : super(CartInitial()) {
    // Synchronously react to auth changes without UI BlocListeners:
    createEffect(() {
      if (authCubit.state.value is Unauthenticated) {
        clearCart();
      }
    });
  }

  final AuthCubit authCubit;
}

5. The 4-Way Code Shootout

Let's look at how the exact same Counter feature looks across all four paradigms:

Option A: Classic Provider (ChangeNotifier)

class CounterModel extends ChangeNotifier {
  int _count = 0;
  int get count => _count;

  void increment() {
    _count++;
    notifyListeners(); // 🚩 Easy to forget; triggers blanket rebuilds
  }
}

Option B: Classic flutter_bloc (Streams + package:provider)

class CounterCubit extends Cubit<int> {
  CounterCubit() : super(0);
  void increment() => emit(state + 1); // ⏳ Asynchronous stream microtask
}

Option C: Riverpod 3 (Code Generation + build_runner)

@riverpod
class Counter extends _$Counter {
  @override
  int build() => 0;

  void increment() => state++; // ⚙️ Requires running build_runner
}

Option D: Modern BlocSignal (Pure, Synchronous Dart)

In Dart 3.5 (Baseline Syntax):

class CounterCubit extends CubitSignal<int> {
  CounterCubit([int initial = 0]) : super(initial);
  void increment() => emit(state.value + 1); // ⚡ Synchronous, zero code-gen
}

In Dart 3.13 (Modern Primary Constructor):

class CounterCubit([int initial = 0]) extends CubitSignal<int>(initial) {
  void increment() => emit(state.value + 1);
}

6. The Ultimate Comparison Matrix

Feature package:provider Classic flutter_bloc Riverpod 3 BlocSignal
Core Reactive Engine ChangeNotifier Asynchronous Stream External DAG Synchronous Signal DAG
Depends on provider? N/A YES (^6.0.0) No NO (Pure SDK)
Requires Code-Gen? No No YES (@riverpod) ZERO Code-Gen
Ghost Rebuild Fix? ❌ (Leaks on branch) ❌ (Inherited leak) ✅ (External Graph) ✅ (Dynamic Graph Pruning)
State Immutability ❌ (Mutable fields) ✅ (Immutable State) ✅ (Immutable State) ✅ (ReadonlySignal)
Execution Timing Synchronous Asynchronous microtask Synchronous Synchronous (Same Frame)
OpenTelemetry & Observers ✅ (BlocObserver) Partial (ProviderObserver) ✅ (Otel + Observers)
Cross-Container Sync Clunky Proxies Nested UI Listeners ref.watch() createEffect / computed

7. The 60-Second Refactor: Your AI Migration Playbook

Five years ago, migrating a production app away from classic BLoC or Provider was a multi-month engineering slog.

In 2026, with modern AI coding assistants (Antigravity, Cursor, Copilot, Gemini) and BlocSignal, the refactor is practically instantaneous:

PROMPT FOR YOUR AI ASSISTANT:
"Replace `flutter_bloc` with `bloc_signals_flutter`.
Replace `BlocProvider` with `BlocSignalProvider`.
Replace `BlocBuilder` with `BlocSignalBuilder`.
Remove `provider` from `pubspec.yaml` and run `flutter pub get`."

💡 Automated AI Migration Skills: The BlocSignal repository even includes pre-packaged AI Agent Skills & Plugins (under plugins/bloc-signals/skills/bloc-signals/) for Antigravity, Cursor, Gemini CLI, and Claude Code. You can install the skill into your workspace to give your AI agent deep, rule-enforced expertise in migrating classic BLoC and Riverpod apps to BlocSignal with full test verification!

In 60 seconds:

  1. All your Blocs and Cubits keep their exact same event and state models.
  2. The asynchronous stream microtask delay disappears.
  3. package:provider is wiped from your pubspec.yaml forever.
  4. Your unit tests run synchronously with zero pumpAndSettle() microtask draining hacks.

8. Summary: Less is More

Software architecture advances not by adding more layers of abstraction, but by removing the friction between your code and the metal.

By removing package:provider and replacing stream plumbing with fine-grained Signals:

  • You eliminate version collisions and dependency solver deadlocks.
  • You fix Flutter’s lingering dependency ghost rebuild bug.
  • You get synchronous, same-frame UI rendering.
  • You preserve 100% of BLoC’s enterprise structure and event traceability.

It's everything you loved about BLoC, everything you wanted from Riverpod, and all the simplicity of Provider—with none of the baggage.

🚀 Get Started with BlocSignal

Read the whole story
alvinashcraft
52 minutes ago
reply
Pennsylvania, USA
Share this story
Delete

EVENT: Microsoft 365 Copilot Roadmap: What’s New & Available – August 25, 2026

1 Share

This month, we’re launching the “AI at Work Webinar: Copilot, Apps, and Agents“.
(Part of the “Microsoft 365 Copilot Roadmap: What’s New & Available” webinar series)

If there’s one thing we hear a lot, it’s that it feels like there’s a new feature, agent, or announcement every month, and finding the time to stay on top of it all isn’t easy.

That’s where this new webinar comes in. Each month, we’ll bring together updates from across Microsoft Copilot, Copilot Studio, Dynamics 365, and other AI-powered experiences into one place, making it easier to stay on top of what’s new, what’s coming next, and why it matters.

What you can expect each month:

  • Updates across Copilot, Copilot Studio, Dynamics 365, and agents
  • What’s coming next and why it matters
  • Demos of the latest features available
  • Live Q&A with experts to answer your questions

Hope to see you there!



Read the whole story
alvinashcraft
52 minutes ago
reply
Pennsylvania, USA
Share this story
Delete

AI Stack Consolidation With a Database-as-a-Service

1 Share

A Database-as-a-Service (DBaaS) is a fully managed data layer that collapses the AI stack into one platform. The concept is simple, but the architecture problem it solves can be extremely complex.

If you’re an enterprise architect or platform engineer supporting a production AI application, the application’s data layer may be spread across a surprisingly large number of systems. You might have one database for operational data, another system for caching, a vector store for retrieval, a search engine, a streaming platform, and an edge database for applications that need to work offline or in the field. Each system adds its own credentials, upgrades, monitoring, and operational overhead. The connections between them add another layer of complexity, with network calls, synchronization jobs, and more potential points of failure that can ultimately affect your agent’s latency and reliability.

This post looks at what AI stack consolidation really means, how to decide which systems to bring together, what a mature DBaaS can replace, and why the platform you consolidate onto matters as much as the decision to consolidate. You can start by exploring Couchbase Capella DBaaS. Or, if you’re still evaluating whether consolidation makes sense for your environment, keep reading.

What AI technology consolidation actually means

AI technology consolidation means replacing a collection of purpose-built point solutions with a single multi-service DBaaS that can handle workloads that previously required several specialized systems. The goal isn’t to add another layer to the modern data stack, but to remove layers.

This distinction matters because the modern data stack has traditionally favored specialization. For example, you would use the best cache for caching, the best vector store for embeddings, and the best search engine for search. That approach can work well when each system operates largely on its own, but it becomes more complicated when an AI agent needs to interact with several systems during a single inference request.

An AI application is still an operational application at its core, so it needs a data layer that can respond quickly, operate across distributed environments, and keep documents, embeddings, and search data in sync. When those capabilities are spread across separate systems, each handoff adds work with another API call, another network request, another serialization step, and another set of credentials to manage. Those costs may be small individually, but they add up across every request.

The point of consolidation isn’t to simplify the architecture simply for the sake of having fewer components. What it’s really about is removing unnecessary handoffs and reducing the operational and performance costs that come with a fragmented data layer.

A unified query language is another important part of making this approach practical. For example, Capella’s SQL++ can work across documents, vectors, full-text search, and key-value data within a single query. This gives the application one interface to the data layer instead of requiring it to coordinate calls across multiple systems and APIs.

The real cost of a fragmented AI stack

Instead of being a one-time setup cost, fragmentation is more like a recurring tax paid on every request, deployment, and on-call incident. The five places it shows up most clearly are:

Latency. Every network hop between systems adds work to the request. An agent might retrieve session state from a cache, pull context from a vector store, and run a full-text search against a separate search engine before it can generate a response. Those calls may be fast individually, but at p99 the delays add up. The user experiences the total latency of the request, not the performance of any one component.

Data duplication. The same document may need to exist in an operational database, a vector index, and a search engine. Keeping those copies aligned requires synchronization pipelines that someone has to build, monitor, and maintain. Even small delays or failures in that process can leave an agent working with inconsistent context.

Operational load. Every additional system brings its own upgrades, failure modes, monitoring requirements, runbooks, and vendor relationships. When something goes wrong at 2 a.m., the on-call engineer may have to trace the problem across several systems before finding the source. Each system added to the stack multiplies the surface area of operational risk.

Cost. Infrastructure is only part of the bill. Teams also pay for data transfer between services, redundant capacity, and the engineering expertise needed to keep each component running reliably in production. For many AI applications, the cost of the surrounding data infrastructure can become significant even though model costs get most of the attention.

Security surface. Each integration introduces another set of credentials, network paths, permissions, and logs to manage. That makes the environment harder to secure and gives security and compliance teams more systems to monitor, audit, and document.

Fragmentation is rarely the result of a single architectural decision. It usually builds over time, with a cache added for performance, a vector store added for retrieval, and a search engine added for better results. Eventually, those individual decisions can leave the team with a stack that is difficult to manage and expensive to operate. Fragmentation definitely has a cost. The big question is whether you can consolidate without giving up the capabilities your application needs. 

Related: Why AI Agents Are Stuck in Pilot. It’s a Data Problem, Not a Model Problem.

A framework for deciding what to consolidate and when

Consolidation doesn’t have to mean rebuilding the entire stack around a single platform. In many cases, the better approach is to look at each component and ask whether keeping it separate still makes architectural and operational sense. The strongest candidates for consolidation are systems that interact frequently with the application, provide little unique value when isolated, and create significant duplication or synchronization overhead. When those considerations outweigh the benefit of specialization, consolidation starts to become a practical choice.

The goal is to identify where consolidation removes real complexity and where specialization still earns its place. Here’s how that plays out across the typical AI stack layers:

Consolidate first: Caching and session state

Caching is often the easiest place to start consolidating because it sits on the critical path of so many requests while offering relatively little differentiation. Applications use it for session state, recent context, and frequently accessed documents, all of which can often be handled by the in-memory capabilities of a DBaaS. Bringing this data closer to the operational data layer can remove a network hop from a high-frequency operation and reduce the number of systems the application has to manage. It also tends to be a relatively low-risk place to begin because the cache can usually be introduced or replaced without changing the underlying data model.

See also: Mastering Caching in the Capella AI Model Service

Consolidate next: Vector, full-text, and operational data

Vector search and full-text search become more useful when they can work directly against the operational data they are helping to retrieve. In a fragmented architecture, an update to a document may need to trigger changes in both a vector store and a search engine. This creates synchronization work and introduces another place where data can become stale or inconsistent. Keeping documents, vectors, and search capabilities together removes much of that coordination. If duplication and synchronization overhead are creating measurable operational or application problems, you have a strong candidate for consolidation.

Consolidate when scale demands it: Real-time and edge

Real-time streaming and edge databases are different because they often exist to solve specific architectural constraints. Streaming may be necessary to move and process data across systems at high volume, while edge databases can support applications that need low-latency access or offline operation. Consolidating these capabilities can make sense when those requirements become part of the core application architecture and the existing seams are creating enough latency, synchronization work, or operational overhead to justify a change. Before that point, replacing a specialized system simply to reduce the system count may add more complexity than it removes.

Keep separate (for now): Specialized analytical and niche engines

Not every specialized system is a good consolidation candidate. A demanding analytical workload may require an OLAP engine optimized for large-scale aggregation, while a graph workload may depend on capabilities that a general-purpose DBaaS does not provide. In cases like these, keeping the specialized system is often the better architectural choice. The objective is not to eliminate every technology outside the DBaaS, but to eliminate the systems whose separation creates more cost and complexity than value.

The most useful way to apply this framework is to look at the actual workload rather than the architecture diagram. Start with the systems the application touches most often, then look at how much unique value each one provides and how much work is required to keep it synchronized with the rest of the stack. Is the interaction frequent, the specialization limited, and the cost of keeping the systems separate significant? Then consolidation is usually worth serious consideration.

What Capella replaces when you consolidate

Here’s what the mature, multi-model Couchbase Capella DBaaS can replace in a production AI stack and what capability it provides in exchange:

Point solutionWhat Capella provides instead
Redis, Memcached (cache)Built-in in-memory tier with sub-millisecond reads. No separate cache to operate.
Pinecone, Weaviate, Milvus (vector store)Native vector search co-located with operational JSON. No sync pipeline.
Elasticsearch, OpenSearch (search engine)Integrated full-text and hybrid search (vector + keyword + filters) in one query.
Separate operational NoSQLDocument database with SQL++: joins, aggregations, secondary indexes, full-text search, and vector in one language.
Edge or mobile databaseCouchbase Lite with automatic bi-directional sync to cloud is offline-capable and provides consistent governance.
RAG plumbing, model hostingAI Data Plane™: vectorization, model hosting, agent catalog, and semantic caching integrated into one platform.

Why a multicloud DBaaS is the right consolidation vehicle

Consolidation only delivers its full value if it reduces operational work along with the number of systems. With a DBaaS like Capella, the database infrastructure is fully managed, including upgrades, backups, scaling, and observability. Your team can consolidate data services without taking on another platform to provision, maintain, and monitor. The result is a simpler data architecture without simply moving the operational burden from one set of systems to another.

Multicloud matters for the same reason. Consolidating onto a managed database in a single cloud can reduce fragmentation, but it can also tie your data architecture more closely to that cloud provider. A multicloud DBaaS that runs consistently across AWS, Google Cloud, and Azure lets you consolidate the data layer without creating the same dependency on a single cloud. You get one security boundary, one governance model, and one operational interface even when workloads run across different clouds.

Couchbase Server provides a self-managed option for teams that need on-premises or air-gapped deployment, or simply require full control over their infrastructure. Capella and Server use the same data model, query language, and core capabilities, giving teams a consistent application architecture across managed and self-managed deployments.

The value of consolidation ultimately depends on what happens to the operational burden. If moving to fewer systems simply means taking on more infrastructure to manage yourself, you’ve reduced the system count without solving the underlying problem. A successful consolidation should leave the team with fewer systems to operate, fewer integrations to maintain, and more time to focus on the application itself.

Ready to evaluate Capella for your AI stack?Try Capella freeTalk to a solutions architect

AI stack consolidation FAQs

What is a Database-as-a-Service (DBaaS)?

A DBaaS is a fully managed cloud database offering with the infrastructure, scaling, backups, upgrades, and observability all handled by the provider rather than the customer’s engineering team. Teams interact with the database through standard APIs and query languages while the platform manages the operational layer underneath. For AI workloads, a multi-model DBaaS goes further, combining operational data, vector search, full-text search, caching, and edge sync in a single managed platform rather than requiring separate managed services for each capability.

What is AI technology consolidation?

AI technology consolidation is the architectural process of collapsing the multiple purpose-built data systems that support a production AI application. This typically includes consolidating an operational database, a cache, a vector store, a search engine, and a streaming or edge layer into a single multi-model DBaaS. The goal is to eliminate the latency, data duplication, operational overhead, cost, and security surface that accumulates at the seams between those systems.

When should you consolidate your AI data stack?

Consolidate a layer when three conditions are simultaneously true: interaction frequency is high, differentiation value is low, and the duplication or synchronization cost is real and measurable. Start with caching and session state, which have the highest frequency, lowest differentiation, and fastest ROI. Next, move to vector and search consolidation when data drift and sync complexity are measurable pains. Keep truly specialized systems like deep graph engines and complex OLAP workloads separate until a better fit exists.

What can Couchbase Capella replace in an AI stack?

Capella can replace a Redis or Memcached cache, a standalone vector database like Pinecone or Weaviate, a search engine like Elasticsearch, a separate operational NoSQL database, an edge or mobile database, and RAG plumbing or model hosting infrastructure. Capella provides a built-in in-memory tier, native vector search co-located with operational data, integrated full-text and hybrid search, a document store with SQL++ query language, Couchbase Lite with automatic cloud sync, and AI Data Plane.

What’s the difference between consolidation and just adding another platform?

Consolidation reduces the number of systems in the stack and eliminates the seams between them. The point is to remove systems rather than add a new platform on top of existing ones. True consolidation means the point solutions go away, replaced by capabilities native to the destination platform. A consolidation isn’t actually a consolidation unless the number of systems you operate goes down.

The post AI Stack Consolidation With a Database-as-a-Service appeared first on The Couchbase Blog.

Read the whole story
alvinashcraft
52 minutes ago
reply
Pennsylvania, USA
Share this story
Delete

.NET Toolbox August Update

1 Share

Quite some time passed since I posted a changelog to the .NET Toolbox. And there are big news: The Toolbox is running dotnet native in the browser thanks to wasm and Mono!

Read the whole story
alvinashcraft
52 minutes ago
reply
Pennsylvania, USA
Share this story
Delete

📱 Four iOS apps, one year, and a lot of help from AI

1 Share

In September of 2025 I started tinkering building an iPhone app. Before this amazing AI wave I thought I would need to retire, learn Swift UI and spend the better part of a few months learning the basics of how to build an iOS app. Well it turns out I was wrong and I have now built 5 iOS apps that are published on the App Store.

It all started with an idea my sister Nevine and I discussed.

Thanks for reading OmarKnows! Subscribe for free to receive new posts and support my work.

My photo library has tens of thousands of photos in it, and every attempt to clean it up died the same way: I would open Photos, scroll for ten minutes, feel overwhelmed, and close it. What if instead of looking at everything, I only looked at the photos taken on this day across all the years? Today’s date, every year I have owned an iPhone. A small, finite pile. Something I could actually finish over coffee.

So I built it. And the surprising part was not the cleanup. It was that looking at one day across all those years connected me to my memories and my past in a way that scrolling never had. Kids at every age. Trips I had half forgotten. That turned it from a chore into something I looked forward to, and it’s why I kept going: widgets so the day’s memories are on my Home Screen, a morning notification with a photo from that day, and sharing so I could send those memories to family.

That first app was an early experiment in building with AI. I used Cursor and Claude Opus 4.5 and 4.6, and I learned a lot about what worked and what didn’t. At the start of 2026 I moved to Codex and Claude Code as my main tools, got faster and better at this, and the apps started coming out quicker. Somewhere along the way I started calling it Omar’s Software Factory.

Here is what came off the factory floor. All four are on the App Store, all four are built for iOS 26, and none of them have accounts, ads, or tracking. Details for each live at omarknows.app.

On This Day

On This Day is the app that started it all. Open it and you see every photo and video you took on today’s date, across every year. Swipe right to keep, swipe left to delete. Deletes are queued until you’re done, and at the end of a session it tells you how much space you actually got back.

The daily part is what makes it work. You don’t clean up your library. You clean up one day, and tomorrow there’s a new day waiting. There’s a streak, a calendar with a dot on every day you’ve finished, and a random day button for when today is thin.

The parts I added because I kept wanting them:

  • Widgets in three sizes that show today’s memory and roll over at midnight.

  • A morning notification with a photo from this day in a past year. It’s a nice way to start the day.

  • Sharing that includes the date and the place the photo was taken. Sending a “ten years ago today” photo to Lora or the kids is my favorite part.

  • Group by Year in the grid, so you can jump straight to 2014.

  • Live Photos and video play inline, EXIF metadata is a tap away, and you can add the whole day to an album.

Everything happens on your phone. Photos never leave the device, and the only thing that syncs through iCloud is your keep and delete decisions so you don’t see the same photo twice.

On This Day is free until you’ve reviewed seven days. After that it’s $1.99 a month, $19.99 a year, or $59.99 for life, which unlocks unlimited days, the widgets, and custom app icons. iPhone only for now.

Tallyday

I wanted a counter for the things in life that don’t have a natural log. Days since I got married. Days since I started at Microsoft. Days since I started Strength Training. So I built Tallyday.

Each counter is a card with a name, an icon, and a color. Tap it, hit Reset, and you’re back to day zero. Tap the number and it flips from total days to years, months, and days. It counts down too: set a date for a trip or a launch, watch the days tick away, and when the day arrives it celebrates and then quietly starts counting up.

There are widgets (one counter, two side by side, or a list), reminders on whatever cadence you like, categories, archive, and search. Your counters sync through your own iCloud, so they show up on your iPad without an account. You can share a milestone as a card, or send it as a link. And a fun detail: the link never touches a server. The milestone lives inside the URL itself, so nothing about your counter is logged anywhere.

Tallyday is free. There’s a tip jar if you want to say thanks, and tips unlock nothing but my gratitude. iPhone and iPad.

Share Times

Every week I have some version of this exchange: “Do you have time Thursday?” “Sure, what works?” “How about 2?” “Is that your 2 or my 2?”

Share Times is my answer. It shows your real calendar as a day timeline, you tap or drag on the empty spots to mark when you’re free, and it produces a clean block of text you can paste into Messages, Mail, or Slack.

The killer feature is time zones. Add the recipient’s time zone and Share Times converts every slot into their local time, so the message reads correctly on their end. No mental math. It handles 15, 30, or 60 minute blocks, working hours, and it skips weekends by default. Recipients can tap the times and see them in their own calendar.

There’s also a three-day calendar widget: a clean, glanceable view of the next few days that looks great with iOS 26.

Share Times is free for a single calendar. Pro is $4.99 a year or $19.99 for life and adds multiple calendars, recipient time zones, the widgets, and lets you remove the “sent with Share Times” line. iPhone only.

Netgleam

Netgleam is the newest one, and it came from travel frustration. Hotel Wi-Fi that connects but doesn’t work. Airport lounges where the captive portal never pops up. Airplane Wi-Fi that says it’s fine while nothing loads. I wanted one app that could tell me plainly what my connection was actually doing.

Netgleam does that. Open it and you get a status card: online or not, Wi-Fi or cellular, link quality, IPv4 and IPv6, whether you’re on a metered connection, whether traffic is going through a VPN or Private Relay. If it detects a captive portal, there’s a one-tap button to open it. I tested that one live on lounge Wi-Fi at JFK and on Alaska’s inflight Wi-Fi, and both were the kind of networks that fool Apple’s built-in detection.

The other tabs:

  • Public IP shows what the internet sees about you: address, ISP, ASN, approximate location, and whether you’re routing direct or through a tunnel.

  • Cellular shows every line on the phone (dual SIM and eSIM included), radio type, and registration state. It only shows what iOS actually exposes, and I decided early on not to invent signal bars or labels Apple won’t give third-party apps.

  • Diagnostics runs eight timed checks (DNS, TCP, TLS, first byte, and so on) and gives you a plain-language verdict with next steps, not a wall of output.

  • Speed test is a native Swift port of Cloudflare’s open source adaptive speed test methodology. Same endpoints, same approach, no web view.

There’s a private connection timeline that records handoffs and IP changes, and history stays on the device.

Netgleam is $0.99, one time. iPhone and iPad.

What I learned

The photos app took about three months of nights and weekends in the fall of 2025 to get to something I loved using, and then another six months of polish and App Store readiness before I shipped it. Tallyday went from first commit to the App Store in a day and to a solid 1.0 in a couple of weeks. Netgleam went from a design spec to live on the App Store in about twelve days.

That’s not because the later apps are simpler. It’s because the tools got dramatically better and I got better at using them. Codex and Claude Code write the code, review each other’s pull requests, run the tests, generate the App Store screenshots, and handle the release pipeline. My job became deciding what to build, using it every day, and being picky about the details.

The single biggest lesson: build the thing you want to use. On This Day is on my Home Screen because I open it every morning. Netgleam exists because I was annoyed in an airport. That’s a much better filter than any market research.

If you try any of these, I’d love to hear what you think. Every app has a support email that goes to me, and I read all of it. And if you’ve got an idea for something small and useful that should exist on your iPhone, tell me in the comments. The factory has capacity.

Thanks for reading OmarKnows! Subscribe for free to receive new posts and support my work.

Read the whole story
alvinashcraft
3 hours ago
reply
Pennsylvania, USA
Share this story
Delete

Amazon is trying to crush class-action suits before they get started

1 Share
An illustration of the Amazon logo

On Friday, Amazon customers received an email alerting them to an update to the site's terms and conditions. Most notably, it stated that disputes would now be resolved through arbitration and said users agree to a class action waiver.

Amazon framed this as a "fast and efficient" way to resolve issues, but it notably would prevent customers from seeking the involvement of a judge or jury in most circumstances. Customers can still take Amazon to small claims court in certain circumstances, though payouts are often limited to a few thousand dollars.

The relevant sections of Amazon's legal policies page now read:

YOU AND WE AGREE THAT ANY …

Read the full story at The Verge.

Read the whole story
alvinashcraft
3 hours ago
reply
Pennsylvania, USA
Share this story
Delete
Next Page of Stories