Native STT vs Deepgram: Which Speech Engine to Choose?
When I launched TAMSIV, all voice recognition went through Deepgram. An excellent cloud service, precise, fast. French? Impeccable. Regional accents? Handled. Automatic punctuation? Perfect. There was just one detail: every second of transcribed audio had a price. And when your app relies entirely on voice, that price quickly climbs.
So I had to make a strategic choice: either I keep Deepgram for everyone and pass the cost on to subscriptions, or I find a free alternative for the Free plan and reserve Deepgram for paying users. I chose the second option. Here's how I built a dual native STT + Deepgram architecture, and what I learned by comparing the two in real-world conditions.
Key takeaways:
- Native STT (Google/Apple) is free, local, and sufficient for short dictations
- Deepgram remains superior in accuracy, especially in noise and with accents
- A dual architecture allows offering a viable free plan without sacrificing premium quality
- Frontend abstraction means components don't know which engine is running
- The choice between native STT vs. cloud is configurable by the admin without app updates
Why is voice recognition so central to a productivity app?
TAMSIV isn't a classic productivity app where you type lists. It's an app where you speak. You dictate a task, a memo, an event. The voice assistant understands what you say, creates the item, and responds to you. Everything goes through voice.
This means that the quality of the transcription directly impacts the experience. If the STT misunderstands "buy bread" and transcribes "buy bath," the user loses confidence. If punctuation is missing, the memo becomes an unreadable block of text. STT is not a gadget — it's the foundation of the entire user experience.
That's why I spent time carefully building the complete voice pipeline. STT is the first step in the chain: Audio → STT → Text → LLM → Function Calling → TTS → Audio. If the first step fails, everything else collapses.
How does native STT work on Android and iOS?
Every modern smartphone includes a voice recognition engine. On Android, it's Google's SpeechRecognizer. On iOS, it's Apple's Speech framework. These engines are integrated into the operating system and work locally — no data leaves the phone.
The advantages are clear:
- Free: No cost per second, no request limits, no surprise bills.
- Local: Voice data stays on the device. Perfect for privacy.
- Fast: No network latency. Transcription starts almost instantly.
- Offline: Works even without an internet connection (with downloaded models).
But there are limitations. Native STT is not designed for professional use cases. Punctuation is often missing or approximate. Accuracy significantly decreases in noisy environments. And for French with accents (Quebecois, African, Belgian), the results vary greatly.
What more does Deepgram offer?
Deepgram is a specialized cloud STT service. Its Nova-2 model is trained on billions of hours of audio and offers remarkable accuracy. Here's what sets it apart from native STT:
- Automatic punctuation: Sentences are correctly punctuated, making memos immediately readable.
- VAD (Voice Activity Detection): Deepgram detects when you speak and when you pause. No transcription of ambient noise.
- WebSocket Streaming: Audio is transcribed in real-time via WebSocket, word by word. The user sees their dictation appear as they speak.
- Native Multi-language: French, including with accents, is well supported.
- Intelligent Endpointing: Deepgram knows when you've finished speaking, which triggers LLM processing at the right time.
The cost? Approximately $0.0043 per minute of streaming audio. It seems small, but for a voice app where each interaction lasts 10 to 30 seconds, it adds up quickly with hundreds of active users.
How did I design the dual architecture in TAMSIV?
The goal was clear: offer two interchangeable STT engines, without the UI code needing to know which one is running. The pattern is one of abstraction — a common interface, two implementations.
On the frontend (React Native), I expose a unified interface:
// Common interface
interface STTEngine {
start(): void;
stop(): void;
onResult(callback: (text: string) => void): void;
onError(callback: (error: Error) => void): void;
}
// Two implementations
class NativeSTTEngine implements STTEngine { ... }
class DeepgramSTTEngine implements STTEngine { ... }
The choice of engine is determined by two factors:
- User plan: Free → native, Pro/Team → Deepgram (configurable).
- Admin configuration: Via the
app_configtable in Supabase, I can force an engine for all users. Useful for A/B testing or in case of a problem with a provider.
UI components (the Dictaphone, the conversation screen) don't know which engine is running. They call start(), stop(), and receive text. This is the single responsibility principle applied to the voice pipeline.
What are the results of the real-world comparison?
I tested both engines on three concrete scenarios, with the same content dictated in French:
| Scenario | Native STT | Deepgram |
|---|---|---|
| Quiet environment | ~92% | ~98% |
| Background noise (cafe, street) | ~75% | ~94% |
| French with accents | ~80% | ~95% |
| Fast dictation (>150 words/min) | ~70% | ~93% |
The verdict is clear: Deepgram is objectively superior in all scenarios. The gap widens particularly in noisy environments and with accents. Deepgram's automatic punctuation is a huge advantage for voice memos — a memo without punctuation is a tedious block of text to reread.
But — and this is the important nuance — for dictating a short task ("Buy milk tomorrow morning"), native STT is sufficient. In a quiet environment, 92% accuracy on a 5-word sentence works. The user can always edit the text after voice creation.
How does this architecture serve the economic model?
The dual architecture is not just a technical feat — it's a business choice. It allows for three things:
- A viable Free plan: Free users can use voice without it costing me anything in STT. The cost is zero because processing is local.
- An argument for premium: "Do you want better accuracy, especially in noise? Go Pro." Users who have tried native and want better have a concrete reason to pay. This is the same principle I apply to RevenueCat subscriptions.
- A security fallback: If Deepgram has an outage (it happens), I can switch all users to native by changing a value in
app_config. No app update needed. This is the same fallback pattern I use for the LLM via OpenRouter.
What are the technical challenges of native STT integration in React Native?
Integrating native STT into React Native is not trivial. Here are the problems I encountered:
- Different Android/iOS APIs: Android's SpeechRecognizer and iOS's Speech framework have completely different APIs. The React Native library I use abstracts some of these differences, but not all.
- Lifecycle management: On Android, the SpeechRecognizer must be properly cleaned up when the app goes into the background. Otherwise, it continues to listen and consumes battery. I had to add listeners on AppState to manage this.
- Security timeout: Native STT can remain stuck in a "listening" state indefinitely. I added a 30-second timeout (the same pattern as in the AudioPlayerService) with automatic cleanup.
- No reliable streaming: Unlike Deepgram which sends words as they are spoken, native STT returns partial results that can be contradictory. I had to implement a debounce to avoid "flickering" of the displayed text.
How to configure STT choice remotely without deploying?
One of the advantages of this architecture is remote configurability. In Supabase, I have an app_config table that stores global application parameters. The choice of STT engine is one of them.
When the app starts, it reads the config from Supabase (or from cache, thanks to the ContentCacheService). If the config says "native for all," even Pro users use native. This is useful in several cases:
- Deepgram outage: Switch instantly without an update.
- A/B testing: Compare retention metrics between the two engines on a user panel.
- Temporary cost reduction: If the cloud budget is tight in a given month, I can temporarily disable Deepgram.
The admin dashboard displays usage metrics by STT engine, allowing for informed decisions.
What is the future of STT in mobile apps?
The STT landscape is evolving rapidly. OpenAI's Whisper has democratized high-quality open-source STT models. Projects like whisper.cpp allow Whisper to run directly on mobile, with quality close to Deepgram and zero cloud cost.
I am closely monitoring this evolution. The day a Whisper model runs well enough on a standard smartphone with real-time French support, cloud STT will become optional for everyone. In the meantime, the dual architecture I have implemented is perfectly positioned to integrate a third engine without touching the UI components.
FAQ
Does native STT work offline?
Yes, provided the language model is downloaded to the device. On Android, Google offers voice model downloads in the settings. On iOS, models are generally already present. Offline quality is slightly lower than the online version.
Is Deepgram the best cloud STT service?
Deepgram Nova-2 is among the best for value for money. Google Cloud Speech-to-Text and AWS Transcribe are serious alternatives. I chose Deepgram for its native WebSocket API and its per-second billing (not per-minute).
Can the user choose their STT engine?
Currently, the choice is linked to the plan (Free = native, Pro = Deepgram). Eventually, I plan to add a toggle in the settings so that Pro users can choose native if they prefer local privacy.
How to handle languages other than French?
TAMSIV supports 6 languages. Both native STT and Deepgram support these languages. Language detection is based on app settings (no automatic detection), which avoids confusion between similar languages.
Does native STT consume a lot of battery?
Less than cloud STT, because there is no network transfer. But local processing uses the phone's processor. For a short dictation (30 seconds), the impact is negligible. For a long dictation (5+ minutes), native STT can consume more battery than cloud because the processor runs continuously.