You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
title: "DSPy solves prompting problems and creates production ones"
3
-
description: "DSPy is an invaluable tool for AI workflow prototypes which creates new headaches in production."
4
-
pubDate: 2026-04-02
2
+
title: "DSPy's abstractions worked for us, but its runtime didn't"
3
+
description: "DSPy is a useful AI workflow development tool, but its runtime configuration introduced issues for our production workflows."
4
+
pubDate: 2026-04-06
5
5
---
6
6
7
-
I felt a pang of jealousy after enjoying [Skylar Payne's write-up on DSPy](https://skylarbpayne.com/posts/dspy-engineering-patterns/). Fantastic post! It deserves a read for its all-too-accurate description of the path taken by [DSPy](https://dspy.ai) (or any half-baked implementation of its concepts) into production, as well as the centrality of
8
-
- typed signatures,
9
-
- composable modules, and
10
-
- prompt optimizers
11
-
in successful AI workflows.
7
+
I greatly enjoyed Skylar Payne's write-up on [DSPy](https://skylarbpayne.com/posts/dspy-engineering-patterns/). I felt it would be helpful to share my experiences building production workflows with DSPy for two separate projects in 2025 at [Not Diamond](https://www.notdiamond.ai/).[^1]
12
8
13
-
My jealousy stems from procrastinating on a similar post describing my experiences building production workflows with DSPy for two separate projects in 2025 at [Not Diamond](https://www.notdiamond.ai/).[^1]This is that post. Thanks, Skylar, for the well-written kick-to-the-butt.
9
+
This is that post. Thanks, Skylar, for the well-written kick-to-the-butt.
14
10
15
-
## The concepts don't block adoption
11
+
## Learning the library v. using it
16
12
17
-
Anyway, we diverge on his conclusion. Skylar writes:
13
+
I agree with the criticality of signatures, modules and optimizers in modern AI workflows. DSPy uses these concepts to great effect; between that, its comprehensive library of prompt-optimizing algorithms, and its excellent documentation, we quickly learned the library.
18
14
19
-
> DSPy has adoption problems because it asks you to think differently before you’ve actually felt the pain of thinking the same way everyone else does.
20
-
21
-
> The patterns DSPy embodies aren’t optional. If your AI system gets complex enough, you will reinvent them. The only question is whether you do it deliberately or accidentally.
22
-
23
-
We agree that AI engineers absolutely must understand signatures and interfaces, both exemplified by the ubiquity of structured outputs. Optimizers - as a component of workflow evals - are similarly critical today.
24
-
25
-
But these concepts are not too esoteric to hinder DSPy’s adoption. Engineers can use DSPy's heaps of excellent documentation to quickly learn its concepts, which align with common practices for evals and workflow optimization. Let's give folks the benefit of the doubt, and assume a new user can quickly reach competency in DSPy.
26
-
27
-
My view is that Skylar has mixed up the causality here. Engineers don't struggle with DSPy because of its novel concepts. Instead, **DSPy's limitations hinder the creation of modular, optimizable AI workflows**.
28
-
29
-
During our testing I observed three concrete limitations in DSPy:
30
-
- Its optimized programs have limited portability,
31
-
- It takes a strongly-opinionated approach to concurrency, and
32
-
- It has an LLM client dependency which can be challenging to work with and tedious to replace.
15
+
That said, I tried to apply DSPy to a specific flavor of distributed system: async-optimized throughput, cross-provider targets, supporting multi-workflow stakeholders in enterprise settings. Its runtime didn't work with our production system, however, so we pulled it.
33
16
34
17
## Conflicting concurrency
35
18
36
-
Both of my team's attempts at integrating DSPy into live workflows involved distributed, asynchronous training and dynamic model-switching via Celery with `gevent`. Users switch LMs via `dspy.configure`, but we encountered[this](https://github.com/stanfordnlp/dspy/blob/main/dspy/dsp/utils/settings.py#L159-L163) configuration issue:
19
+
Both of my team's attempts at integrating DSPy into live workflows involved distributed, asynchronous training and dynamic model-switching via Celery with `gevent`. We abandoned DSPy shortly after encountering[this](https://github.com/stanfordnlp/dspy/blob/main/dspy/dsp/utils/settings.py#L159-L163) configuration issue:
37
20
38
21
```python
39
22
ifnot in_ipython and config_owner_async_task != asyncio.current_task():
@@ -43,7 +26,7 @@ if not in_ipython and config_owner_async_task != asyncio.current_task():
43
26
)
44
27
```
45
28
46
-
As suggested, we tried`dspy.context`to avoid async task conflicts. But every model switch required context managers, [as demonstrated by this example snippet](https://github.com/stanfordnlp/dspy/blob/main/docs/docs/tutorials/cache/index.md?plain=1#L178-L181):
29
+
So we used`dspy.context`, as suggested to avoid async task conflicts. As mentioned before, though, we wanted to switch models, which obligated [this example snippet](https://github.com/stanfordnlp/dspy/blob/main/docs/docs/tutorials/cache/index.md?plain=1#L178-L181):
47
30
48
31
```python
49
32
with dspy.context(lm=dspy.LM("openai/gpt-5-mini")):
@@ -53,18 +36,21 @@ with dspy.context(lm=dspy.LM("openai/gpt-5-nano")):
53
36
result2 = predict(question="Who do *you* think is the GOAT of soccer?")
54
37
```
55
38
56
-
In a Markdown doc or Jupyter notebook this reads fine. In a production codebase this practically _invites_ bugs. We abandoned both efforts shortly thereafter.
57
-
58
39
While DSPy 3.0 shipped async improvements, [limitations in configurability](https://github.com/stanfordnlp/dspy/issues/8197) and async support still persist:
59
-
- program training still [requires a synchronous context](https://github.com/stanfordnlp/dspy/issues/9075)
40
+
- program training seems to [require a synchronous context](https://github.com/stanfordnlp/dspy/issues/9075)
60
41
-`dspy.settings` has [mixed support](https://github.com/stanfordnlp/dspy/issues/8197) across coroutines
61
42
- multi-model workflows have limited support across [different concurrency models](https://github.com/stanfordnlp/dspy/issues/8797)
62
43
63
-
More broadly, **this anti-modular design emerges from DSPy's tightly-coupled inference-time story**. By optimizing your program with DSPy, you've also bought into the library's architectural decisions for concurrency. This is no more evident than [in the FastAPI tutorial](https://dspy.ai/tutorials/deployment/#deploying-with-fastapi), where the user defers concurrency management to DSPy via `dspy.asyncify`. But production deployments require performance optimizations tailored to the needs of *your* workflows - not those of a library dependency.
44
+
More broadly, **this design tightly couples DSPy's runtime to your production setting**. By optimizing your program with DSPy, you've also bought into the library's architectural decisions for concurrency. This is no more evident than [in the FastAPI tutorial](https://dspy.ai/tutorials/deployment/#deploying-with-fastapi), where the user's concurrency management must be deferred to DSPy via `dspy.asyncify`.
45
+
46
+
Our production deployment requires performance optimizations tailored to the needs of *our* workflows, instead of those of a library dependency. To avoid conflicts between Celery and DSPy's concurrency management, we essentially distributed prompt optimization by model and ran each optimizer serially within a task.
64
47
48
+
This architecture wrecked the system's overall throughput. DSPy's optimizers were now the slowest part of our optimization stack.
65
49
## Pulling prompts
66
50
67
-
What did I mean earlier by a "tightly-coupled inference-time story?" Let's say you want to use your optimized prompts outside of DSPy. You'd have to extract them [like so](https://github.com/stanfordnlp/dspy/issues/7830):
51
+
Once optimization completed, we encountered additional challenges when porting optimized prompts out of the distributed tasks. These prompts needed to pass human review for use in workflows which did not depend on DSPy, or existed outside of automated pipelines altogether (like AI chat interfaces).
52
+
53
+
Let's say you want to use your optimized prompts outside of DSPy. You'd have to extract prompts [like this](https://github.com/stanfordnlp/dspy/issues/7830):
68
54
69
55
```python
70
56
{
@@ -77,55 +63,33 @@ What did I mean earlier by a "tightly-coupled inference-time story?" Let's say y
77
63
}
78
64
```
79
65
80
-
Omar Khattab[^2] has [explained the intention](https://github.com/stanfordnlp/dspy/issues/8042#issuecomment-2773833904) behind this choice:
81
-
82
-
> DSPy does a lot of heavy-lifting indeed, and it's very common that people try to extract the optimized prompt but end up hurting quality in the process. We do not usually advise that you extract anything for this reason, since the optimized prompt assumes a lot of DSPy behavior like the way the inference calls are made.
83
-
84
-
> That said, if you really want to get a prompt you can apply this process. Note that it gives you a list of messages.
85
-
86
-
He's right, of course. Many of DSPy's optimizers[^3] treat signatures as optimizable parameters. If the user decouples those components from the underlying prompts, they can inadvertently unwind performance gains.
87
-
88
-
But...that's _my_ prompt. Now, though, it has limited applicability. Concretely: **this inference-time requirement creates a golden-path dependency on DSPy.**
89
-
90
-
This bleeds into other concerns. For eg. observability, we faced a choice between forking the library to add spans or adopting [MLflow](https://dspy.ai/tutorials/observability/#tracing). If your production service doesn't use Python, you're instead relying on unofficial ports[^4]. If your prompt needs to land in a non-software workflow handled by Claude Cowork or Codex? You're back to Omar's earlier snippet.
91
-
66
+
Note that many of DSPy's optimizers[^2] treat signatures as optimizable parameters. If the user decouples those components from the underlying prompts, they can inadvertently unwind performance gains. Users should preserve DSPy's programs as-is.
92
67
68
+
**But these programs do not willingly exit the DSPy runtime**. We attempted to extract programs using the above snippet, as well as applying various scripts to DSPy's JSON I/O options and its `Signature` and `ChatAdapter` classes. None of these approaches ultimately met the requirements of our end users for workflow compatibility and human understanding.
93
69
## Dealing with dependencies
94
70
95
-
DSPy also relies on leaky abstractions thanks to its underlying LLM client library, LiteLLM. Several years ago, LiteLLM's cross-provider compatibility and ease of implementation made it the de-facto LLM client for workflow prototyping. Since then the AI ecosystem aligned onto OpenAI-style messages, and Skylar’s post demonstrates common patterns in client usage and request retries.
71
+
Our production runtime deploys into environments with tighly-constrained requirements, so we require control over our supply chain. DSPy, however, executes all of its LLM client requests via LiteLLM. Introducing DSPy meant accepting LiteLLM into our carefully-curated environments and observability stack.
96
72
97
-
LiteLLM poses its own issues in production contexts, however, such as poor logging configuration. It produces verbose, poorly-formatted logs at `INFO` level, which polluted Datadog, Sentry and our local testing tools:[^5]
73
+
I've found that LiteLLM presents significant issues in non-trivial production contexts. The library introduces verbose, poorly-formatted logs at `INFO` level, which polluted Datadogand our local testing tools:[^3]
98
74
99
-

75
+

100
76
101
-
LiteLLM also recently experienced [a supply chain vulnerability](https://docs.litellm.ai/blog/security-update-march-2026) after a core maintainer's PyPI credentials were compromised. This risk exists for any OSS project, but if LiteLLM is not proxying your requests then your alternatives can be as simple as `openai.OpenAI` and `tenacity`. [^6]
77
+
Our supply chain requirements extend to security concerns, so it's worth noting LiteLLM recently experienced [a supply chain vulnerability](https://docs.litellm.ai/blog/security-update-march-2026), where a core maintainer's PyPI credentials were seemingly compromised.
102
78
103
-
In DSPy, users can swap out the underlying client library with some effort. [There's no documentation on this capability](https://dspy.ai/learn/programming/language_models/#advanced-building-custom-lms-and-writing-your-own-adapters). A DSPy contributor is working on extracting LiteLLM into an extra dependency [while redesigning `dspy.LM`](https://github.com/stanfordnlp/dspy/issues/9514), which significantly helps production users once the change lands.
79
+
We overcame these challenges by building our own client logic with `openai.OpenAI` and `tenacity` which extends across structured outputs and function calling.[^4] As of today there's broad support for `chat.completions` across AI providers. Our in-house client library works comprehensively and reliably, thanks to strong compatibility with our observability stack.
104
80
105
81
## What it is and what it is not
106
82
107
-
Admittedly, our experience with DSPy could confirm "Khattab's Law" as proposed by Skylar:
108
-
109
-
> Any sufficiently complicated AI system contains an ad hoc, informally-specified, bug-ridden implementation of half of DSPy.
83
+
If you need to manage your own concurrency, port your prompts to different settings, or keep an orderly deployment environment, you might find that DSPy's dependency stack and runtime don't fit your needs.
110
84
111
-
Our prompting layer leverages typed signatures, a separate eval harness and first-party provider SDKs to optimize prompts over eval datasets.
112
-
113
-
But none of the facts I've laid out above dilute the usefulness of DSPy. It's still a fantastic exploratory tool for prompt optimization. Our broader AI ecosystem benefits from research produced by labs like Stanford NLP and MIT CSAIL, whose researchers primarily maintain DSPy.
114
-
115
-
That said, it's worth acknowledging difficulties integrating it into production systems with optimized concurrency, comprehensive monitoring, and tight requirements for environment builds.
116
-
117
-
As Skylar noted, DSPy’s concepts form the basis of any well-designed AI workflow. I believe that applying those concepts inward - to the library’s architecture and interfaces - would broaden its impact far beyond prototyping and research.
85
+
For other scenarios, though, DSPy can help launch and optimize your workflow prototypes very quickly, and its concepts will endure well into the production phase of your project.
118
86
119
87
*Thanks to Devansh Jain and James Kunstle for input on this write-up*.
120
88
121
-
[^1]: Astute readers will note that Not Diamond offers [Prompt Optimization](https://www.notdiamond.ai/#prompt-optimization). If you haven't closed this tab yet, I *solemnly vow* to avoid any sales in this post.
122
-
123
-
[^2]: Lead author on [the original DSPy paper](https://arxiv.org/abs/2310.03714) and core contributor to the open-source library.
124
-
125
-
[^3]: Notably, this is not true of GEPA, where users can [seamlessly extract prompts](https://x.com/LakshyAAAgrawal/status/1978198977985069348) from the optimized adapter. While GEPA is available in DSPy, this capability is primarily available in the underlying `gepa-ai`[library](https://gepa-ai.github.io/gepa/).
89
+
[^1]: Astute readers will note that one of our products at Not Diamond is [Prompt Optimization](https://www.notdiamond.ai/#prompt-optimization). If you haven't closed this tab yet, I *solemnly vow* to avoid any sales in this post.
126
90
127
-
[^4]: There are community-built libraries for languages like [TypeScript](https://github.com/ruvnet/dspy.ts) and [Rust](https://github.com/krypticmouse/DSRs). They lack feature parity or ongoing support.
91
+
[^2]: Notably, this is not true of GEPA, where users can [seamlessly extract prompts](https://x.com/LakshyAAAgrawal/status/1978198977985069348) from the optimized adapter. While GEPA is available in DSPy, this capability is primarily available in the underlying `gepa-ai`[library](https://gepa-ai.github.io/gepa/).
128
92
129
-
[^5]: Honestly, "Local Engineer Complains About Dependency Logging Configs" is the least surprising headline of the day! But LiteLLM's usage of `INFO` for low-signal logs feels disconnected from common logging practices in production systems. It's symptomatic of LiteLLM's other issues, a discussion of which falls well outside of this post's scope.
93
+
[^3]: Honestly, "Local Engineer Complains About Dependency Logging Configs" is the least surprising headline of the day! But LiteLLM's usage of `INFO` for low-signal logs feels disconnected from common logging practices in production systems.
130
94
131
-
[^6]: I expect most AI engineers writing Python have battle scars with `openai.OpenAI` and `tenacity.retry` at this point.
95
+
[^4]: I expect most AI engineers writing Python have battle scars with `openai.OpenAI` and `tenacity.retry` at this point. `RETRYABLE_HTTP_ERROR_CODES` should be a permanent fixture of Pythonic AI project templates.
0 commit comments