<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Artem</title>
    <description>The latest articles on DEV Community by Artem (@artem7898).</description>
    <link>https://dev.to/artem7898</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1010855%2F64111c99-cbcc-4974-acee-fe7610f33569.png</url>
      <title>DEV Community: Artem</title>
      <link>https://dev.to/artem7898</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/artem7898"/>
    <language>en</language>
    <item>
      <title>Django Nova: What Changed When I Put the Library Behind a Public Demo</title>
      <dc:creator>Artem</dc:creator>
      <pubDate>Tue, 29 Sep 2026 00:22:27 +0000</pubDate>
      <link>https://dev.to/artem7898/django-nova-what-changed-when-i-put-the-library-behind-a-public-demo-3fpj</link>
      <guid>https://dev.to/artem7898/django-nova-what-changed-when-i-put-the-library-behind-a-public-demo-3fpj</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F50s6ymq1gzum4xympvq3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F50s6ymq1gzum4xympvq3.png" alt=" " width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Cache invalidation, async boundaries, and the work behind &lt;a href="https://novademo.tech/" rel="noopener noreferrer"&gt;novademo.tech&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;During the deployment of Django Nova’s public demo, the application was already returning &lt;code&gt;{"status": "ok"}&lt;/code&gt;. PostgreSQL, Redis, Memcached, and the web container were healthy.&lt;/p&gt;

&lt;p&gt;The same health endpoint through Nginx returned 404.&lt;/p&gt;

&lt;p&gt;That small failure was a useful reminder: a successful check proves something about the layer it reaches. It does not automatically prove that the next layer works.&lt;/p&gt;

&lt;p&gt;I have been learning the same lesson inside Django Nova.&lt;/p&gt;

&lt;p&gt;In my &lt;a href="https://medium.com/@alimpievne/django-nova-fixing-djangos-most-persistent-architectural-problem-5f492bb1f0df" rel="noopener noreferrer"&gt;earlier architecture article&lt;/a&gt;, I focused on duplicated validation and shared schemas. In the &lt;a href="https://medium.com/@alimpievne/django-nova-what-happens-when-you-try-to-make-django-strictly-typed-b5b5968d3e05" rel="noopener noreferrer"&gt;typing follow-up&lt;/a&gt;, I described the difficulty of putting a typed interface around Django’s dynamic metadata.&lt;/p&gt;

&lt;p&gt;Now there is a public application where readers can inspect and exercise some of those ideas:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://novademo.tech/" rel="noopener noreferrer"&gt;https://novademo.tech&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Getting there meant dealing with transactions, mutable cached objects, asynchronous execution, deployment, and recovery. It also meant being more precise about what Nova promises.&lt;/p&gt;

&lt;h2&gt;
  
  
  A shared schema still needs boundaries
&lt;/h2&gt;

&lt;p&gt;Django Nova connects Django models with Pydantic schemas, query planning, caching, and optional integrations. Django’s ORM remains responsible for persistence.&lt;/p&gt;

&lt;p&gt;The original motivation is familiar: an application can repeat similar rules in a serializer, a form, a model, and a background task. As these entry points evolve, their behavior can drift.&lt;/p&gt;

&lt;p&gt;Shared schemas help, but the different validation layers still have work to do.&lt;/p&gt;

&lt;p&gt;In the current implementation, &lt;code&gt;NovaModel.save()&lt;/code&gt; checks the selected Pydantic schema, validates and converts Django fields, runs &lt;code&gt;Model.clean()&lt;/code&gt;, checks uniqueness and model constraints, and then saves through Django. A failure stops the later stages.&lt;/p&gt;

&lt;p&gt;One detail matters more than it initially appears: a value returned by Django’s &lt;code&gt;field.clean()&lt;/code&gt; must be assigned back to the instance before model-level validation runs. Otherwise, a later validator can inspect the original value even though field conversion succeeded.&lt;/p&gt;

&lt;p&gt;There are also write paths that bypass this sequence. &lt;code&gt;QuerySet.update()&lt;/code&gt;, &lt;code&gt;bulk_create()&lt;/code&gt;, and &lt;code&gt;bulk_update()&lt;/code&gt; do not call model &lt;code&gt;save()&lt;/code&gt;. Database constraints remain necessary, particularly when writes race.&lt;/p&gt;

&lt;p&gt;This is a qualification I would add to the stronger language in my earlier article. The useful guarantee is a defined validation path with documented exceptions. Sharing a schema does not make every possible database write pass through it.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://github.com/Artem7898/django-nova/blob/7f3ce44bd3f1e6998547867f650e075c312571fd/docs/validation.md" rel="noopener noreferrer"&gt;validation guide&lt;/a&gt; describes that contract.&lt;/p&gt;

&lt;h2&gt;
  
  
  Types helped expose assumptions
&lt;/h2&gt;

&lt;p&gt;One failure from the typing work still captures the problem well.&lt;/p&gt;

&lt;p&gt;I had treated a primary key as a field that must pass Nova’s general-purpose concrete-field filter. Django already had an authoritative answer in &lt;code&gt;_meta.pk&lt;/code&gt;. My abstraction was imposing an extra condition on it.&lt;/p&gt;

&lt;p&gt;The fix was to preserve Django’s definition at that boundary.&lt;/p&gt;

&lt;p&gt;The subsequent runtime work exposed other assumptions: callable defaults evaluated too early, file objects needing a filename representation, and serialization touching relations that the selected schema did not request.&lt;/p&gt;

&lt;p&gt;These are observable behaviors. A type checker can help organize the code around them, but regression tests need to establish what actually happens.&lt;/p&gt;

&lt;p&gt;Even a clean Pyright result has a scope. Nova’s configuration contains exclusions and adjusted diagnostics. It should be read alongside those settings, rather than as a claim that every integration has identical static guarantees.&lt;/p&gt;

&lt;h2&gt;
  
  
  Caching forced me to think about time and ownership
&lt;/h2&gt;

&lt;p&gt;Caching produced some of the most useful engineering work because a successful cache hit answers so few of the difficult questions.&lt;/p&gt;

&lt;p&gt;Consider invalidation during a transaction. A model save may succeed and the surrounding transaction may still roll back. Invalidating on the save signal alone does not establish the right relationship with committed data.&lt;/p&gt;

&lt;p&gt;Nova’s signal-driven invalidation is deferred until the relevant database transaction commits. Rollback discards the callback. Reads inside a transaction use the database.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://github.com/Artem7898/django-nova/blob/7f3ce44bd3f1e6998547867f650e075c312571fd/tests/cache/test_invalidation_transactions.py" rel="noopener noreferrer"&gt;transaction tests&lt;/a&gt; make the timing concrete: they cover commit, rollback, nested savepoints, and database aliases. Their recording cache is intentional; those tests check when invalidation is requested, while backend tests cover the transport.&lt;/p&gt;

&lt;p&gt;Then there is a harder race:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;A reader starts fetching an older database result.&lt;/li&gt;
&lt;li&gt;A writer commits a change.&lt;/li&gt;
&lt;li&gt;The writer invalidates the cached query.&lt;/li&gt;
&lt;li&gt;The original reader finishes and tries to cache its older result.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Deleting an existing key does not, by itself, stop that final write.&lt;/p&gt;

&lt;p&gt;The shared-generation approach associates results with tokens scoped to a model and database alias. A fill keeps the generation captured before its SQL query. After a successful generation change, a late result cannot become an entry in the new generation.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://github.com/Artem7898/django-nova/blob/7f3ce44bd3f1e6998547867f650e075c312571fd/tests/cache/test_shared_cache_generation.py" rel="noopener noreferrer"&gt;regressions&lt;/a&gt; also cover a writer that has never populated the reader’s cache.&lt;/p&gt;

&lt;p&gt;This still does not create an atomic transaction between PostgreSQL and Redis or Memcached. If a writer cannot deliver invalidation during a network failure, another process may retain stale data. That limitation needs an application-specific consistency policy.&lt;/p&gt;

&lt;p&gt;A separate issue concerns ownership of the returned objects.&lt;/p&gt;

&lt;p&gt;Suppose one caller reads cached models and changes a nested JSON value without saving. A later caller must not observe that in-memory edit as if it came from the database.&lt;/p&gt;

&lt;p&gt;The same problem applies to the list itself, model attributes, and already-loaded related objects. Copying only the outer list is insufficient.&lt;/p&gt;

&lt;p&gt;Nova’s &lt;a href="https://github.com/Artem7898/django-nova/blob/7f3ce44bd3f1e6998547867f650e075c312571fd/tests/cache/test_queryset_result_isolation.py" rel="noopener noreferrer"&gt;result-isolation tests&lt;/a&gt; mutate those structures and then check that another read preserves the stored result without falling back to SQL.&lt;/p&gt;

&lt;p&gt;Optimizing those copies requires another distinction: a backend that returns independent values on reads does not necessarily capture independent values on writes. The &lt;a href="https://github.com/Artem7898/django-nova/blob/7f3ce44bd3f1e6998547867f650e075c312571fd/docs/caching.md" rel="noopener noreferrer"&gt;cache contract&lt;/a&gt; treats those as separate capabilities.&lt;/p&gt;

&lt;p&gt;Each of these details adds a question that a simple “miss, then hit” example cannot answer.&lt;/p&gt;

&lt;h2&gt;
  
  
  Async behavior needs its own evidence
&lt;/h2&gt;

&lt;p&gt;An async function introduces another kind of boundary: the difference between creating a coroutine and executing it.&lt;/p&gt;

&lt;p&gt;A tracing wrapper can open a span, call an async function, receive its coroutine, and close the span before the actual work runs. It has measured coroutine creation while missing the awaited operation.&lt;/p&gt;

&lt;p&gt;Nova’s tracing decorators were changed to keep the span open across the await. The &lt;a href="https://github.com/Artem7898/django-nova/blob/7f3ce44bd3f1e6998547867f650e075c312571fd/tests/core/test_tracing_async.py" rel="noopener noreferrer"&gt;tests&lt;/a&gt; verify execution order, exceptions raised after suspension, and cancellation propagation.&lt;/p&gt;

&lt;p&gt;Serialization raises a different async concern. Reading an unloaded foreign key can execute synchronous SQL. An async save API does not automatically make every subsequent access to that model safe inside an event loop.&lt;/p&gt;

&lt;p&gt;I want those distinctions visible in the documentation and the demo. Developers need to know which operation runs, what it waits for, and what could still touch the database.&lt;/p&gt;

&lt;h2&gt;
  
  
  What you can try at novademo.tech
&lt;/h2&gt;

&lt;p&gt;The demo is an application built with Nova, with a product catalog and an interactive lab. It includes a browser-session workspace, schema inspection, API documentation, and Russian and English interfaces.&lt;/p&gt;

&lt;p&gt;Its &lt;a href="https://github.com/Artem7898/nova-demo/blob/2ecbd20d05230dd354ec4c2de7fcd0a4eed5a15e/catalog/lab/registry.py" rel="noopener noreferrer"&gt;scenario registry&lt;/a&gt; currently defines 19 scenarios. They cover validation, serialization, query planning, cache behavior, transactions, result isolation, context handling, tasks, adapters, and infrastructure integrations.&lt;/p&gt;

&lt;p&gt;If you have five minutes, I suggest starting with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Validation:&lt;/strong&gt; change a product’s name or price and inspect the result.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Query planning:&lt;/strong&gt; compare the SQL counts for the same data and relationships.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Commit and rollback:&lt;/strong&gt; inspect when a changed value becomes visible.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Result isolation:&lt;/strong&gt; see whether an unsaved mutation affects another cached read.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The lab also exposes its limits. The task example runs in-process and finishes within the request. The migration scenario previews SQL without executing DDL. GraphQL is an experimental, restricted read-only example. These distinctions are recorded in the &lt;a href="https://github.com/Artem7898/nova-demo/blob/2ecbd20d05230dd354ec4c2de7fcd0a4eed5a15e/docs/CAPABILITIES.md" rel="noopener noreferrer"&gt;capability map&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The deployment uses one Gunicorn worker and one thread because several lab demonstrations involve process-local state. It gives the examples a controlled execution environment; evaluating a deployment with multiple workers requires additional work.&lt;/p&gt;

&lt;p&gt;The displayed timings include instrumentation. They help explain a scenario, but they are not a benchmark establishing general performance advantages.&lt;/p&gt;

&lt;h2&gt;
  
  
  Hosting made the operational work visible
&lt;/h2&gt;

&lt;p&gt;I deployed the site on a Hostinger VPS using Docker Compose, with PostgreSQL, Redis, and Memcached behind the application. Nginx handles public traffic and HTTPS.&lt;/p&gt;

&lt;p&gt;The setup involved several separate checks. An unwanted AAAA record remained after the IPv4 configuration, so I checked the authoritative DNS servers and a public resolver after removing it. The application’s local health endpoint worked before Nginx routed the domain correctly. Certificate issuance succeeded, and the renewal dry run passed.&lt;/p&gt;

&lt;p&gt;That process made the diagnostic order clearer: application, reverse proxy, DNS, then HTTPS. Checking each layer separately made the failures easier to locate.&lt;/p&gt;

&lt;p&gt;Backups required their own definition of success.&lt;/p&gt;

&lt;p&gt;The backup process briefly pauses the web application while PostgreSQL and uploaded files are copied. It resumes the site, checks the archives and checksums, and restores the database dump into a temporary database.&lt;/p&gt;

&lt;p&gt;I also copied the first completed backup to another device and checked its hashes there.&lt;/p&gt;

&lt;p&gt;That establishes more than the existence of an archive. It still leaves work to do: automatic off-server copying is not configured, and a complete recovery of the entire VPS has not been rehearsed. The temporary-database restore is a specific check, with a specific scope.&lt;/p&gt;

&lt;h2&gt;
  
  
  The next useful feedback is a concrete case
&lt;/h2&gt;

&lt;p&gt;The demo pins the published &lt;code&gt;django-nova==0.6.3&lt;/code&gt; package. The main repository and its documentation can evolve separately, so examples should always be checked against the installed release.&lt;/p&gt;

&lt;p&gt;Nova remains beta. The current package declares Python 3.12 or newer, Django &lt;code&gt;&amp;gt;=5.0,&amp;lt;6.0&lt;/code&gt;, and Pydantic &lt;code&gt;&amp;gt;=2.8,&amp;lt;3.0&lt;/code&gt;. Those dependency bounds do not prove every combination has been tested.&lt;/p&gt;

&lt;p&gt;My aim for the public demo is to make discussion more concrete. Readers can start with a behavior, inspect its limits, and compare it with an application they know.&lt;/p&gt;

&lt;p&gt;I would especially welcome cases involving related-object serialization, writes that bypass save hooks, and cached queries with frequent updates. A small model, schema, and failing operation would make useful feedback.&lt;/p&gt;

&lt;p&gt;Which behavior would you need to verify before introducing something like Nova into your Django application?&lt;/p&gt;

&lt;p&gt;Try the demo: &lt;strong&gt;&lt;a href="https://novademo.tech/" rel="noopener noreferrer"&gt;novademo.tech&lt;/a&gt;&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Explore the library: &lt;strong&gt;&lt;a href="https://github.com/Artem7898/django-nova" rel="noopener noreferrer"&gt;Artem7898/django-nova&lt;/a&gt;&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Inspect the demo source: &lt;strong&gt;&lt;a href="https://github.com/Artem7898/nova-demo" rel="noopener noreferrer"&gt;Artem7898/nova-demo&lt;/a&gt;&lt;/strong&gt;&lt;br&gt;
Documentation:&lt;a href="https://artem7898.github.io/django-nova-site/" rel="noopener noreferrer"&gt;Django Nova site&lt;/a&gt;&lt;/p&gt;

</description>
      <category>architecture</category>
      <category>backend</category>
      <category>django</category>
      <category>python</category>
    </item>
    <item>
      <title>Catching Flaky Tests Before They Hit CI: Meet FlakyDetector</title>
      <dc:creator>Artem</dc:creator>
      <pubDate>Sun, 28 Jun 2026 19:36:52 +0000</pubDate>
      <link>https://dev.to/artem7898/catching-flaky-tests-before-they-hit-ci-meet-flakydetector-2e41</link>
      <guid>https://dev.to/artem7898/catching-flaky-tests-before-they-hit-ci-meet-flakydetector-2e41</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fgozrio1jn1kbrgqx8txx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fgozrio1jn1kbrgqx8txx.png" alt=" " width="799" height="605"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;By Artem Alimpiev — Python Backend Developer&lt;/p&gt;

&lt;p&gt;Every engineering team has that test.&lt;/p&gt;

&lt;p&gt;The one that passes locally, passes on your teammate’s machine, passes three times in CI… and then suddenly fails at 2 AM for absolutely no reason.&lt;/p&gt;

&lt;p&gt;So somebody reruns the pipeline.&lt;/p&gt;

&lt;p&gt;Again.&lt;/p&gt;

&lt;p&gt;And again.&lt;/p&gt;

&lt;p&gt;Eventually the build goes green, everyone moves on, and the flaky test quietly stays in the repository like a cursed artifact nobody wants to touch.&lt;/p&gt;

&lt;p&gt;I’ve seen this happen too many times in real projects. And honestly, the bigger the infrastructure becomes, the worse the problem gets.&lt;/p&gt;

&lt;p&gt;At some point I started asking myself a simple question:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Why are we still detecting flaky tests after they break CI?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That question eventually turned into FlakyDetector — an AST + Machine Learning powered system for detecting flaky tests before they hit your pipelines.&lt;/p&gt;

&lt;p&gt;GitHub Repository:&lt;br&gt;
&lt;a href="https://github.com/Artem7898/flakydetector" rel="noopener noreferrer"&gt;FlakyDetector GitHub Repository&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Flaky Tests Are More Expensive Than Most Teams Realize&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;People often treat flaky tests as “just annoying.”&lt;/p&gt;

&lt;p&gt;But flaky tests are actually infrastructure debt.&lt;/p&gt;

&lt;p&gt;They:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;slow down releases&lt;/li&gt;
&lt;li&gt;waste CI resources&lt;/li&gt;
&lt;li&gt;destroy trust in automation&lt;/li&gt;
&lt;li&gt;create false negatives&lt;/li&gt;
&lt;li&gt;normalize ignoring failed builds&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;And that last one is especially dangerous.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Because once engineers stop trusting CI, the entire feedback loop starts collapsing.&lt;/p&gt;

&lt;p&gt;Google engineers once reported that a significant percentage of test failures inside large CI systems were caused by flakiness rather than real regressions.&lt;/p&gt;

&lt;p&gt;Think about that for a second.&lt;/p&gt;

&lt;p&gt;Imagine debugging failures that aren’t even real bugs.&lt;/p&gt;

&lt;p&gt;Now combine that with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;async systems&lt;/li&gt;
&lt;li&gt;distributed services&lt;/li&gt;
&lt;li&gt;parallel test execution&lt;/li&gt;
&lt;li&gt;unstable timing&lt;/li&gt;
&lt;li&gt;shared global state&lt;/li&gt;
&lt;li&gt;external APIs&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Suddenly your test suite behaves less like deterministic engineering and more like a physics experiment.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Most Flaky Detection Tools React Too Late&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The majority of flaky-test tooling works reactively.&lt;/p&gt;

&lt;p&gt;Usually the workflow looks like this:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Write test ↓ Push code ↓ CI randomly fails ↓ Retry pipeline ↓ Lose 40 minutes of engineering time&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Traditional systems rely on:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;rerun statistics&lt;/li&gt;
&lt;li&gt;CI telemetry&lt;/li&gt;
&lt;li&gt;historical failure tracking&lt;/li&gt;
&lt;li&gt;probabilistic heuristics&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Useful? Absolutely.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Preventive? Not really.&lt;/p&gt;

&lt;p&gt;I wanted something different.&lt;/p&gt;

&lt;p&gt;I wanted a system that could analyze the source code itself and detect risky patterns before the tests ever started failing in production CI environments.&lt;/p&gt;

&lt;p&gt;That’s where AST analysis became incredibly interesting.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;AST Analysis: Looking at Code Structurally&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If you’ve never worked with Python ASTs directly, here’s the simple explanation.&lt;/p&gt;

&lt;p&gt;Python code isn’t just text.&lt;/p&gt;

&lt;p&gt;Under the hood, Python converts code into an Abstract Syntax Tree — a structured representation the interpreter can reason about.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;isn’t stored as plain text internally.&lt;/p&gt;

&lt;p&gt;It becomes semantic structure:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;function call&lt;/li&gt;
&lt;li&gt;module reference&lt;/li&gt;
&lt;li&gt;execution dependency&lt;/li&gt;
&lt;li&gt;timing behavior&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And once you have structure, you can detect patterns.&lt;/p&gt;

&lt;p&gt;That changes everything.&lt;/p&gt;

&lt;p&gt;FlakyDetector scans Python test suites and searches for architectural anti-patterns associated with nondeterministic behavior.&lt;/p&gt;

&lt;p&gt;Examples include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;`time.sleep()&lt;/li&gt;
&lt;li&gt;datetime.now()`&lt;/li&gt;
&lt;li&gt;mutable global state&lt;/li&gt;
&lt;li&gt;unmocked network requests&lt;/li&gt;
&lt;li&gt;dangerous fixture scopes&lt;/li&gt;
&lt;li&gt;resource leakage&lt;/li&gt;
&lt;li&gt;high cyclomatic complexity&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Or in testing terminology:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Test Smells.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Yes, that’s a real technical term. And yes, it sounds slightly ridiculous.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why I Added Machine Learning&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;At first, FlakyDetector started as a pure AST rule engine.&lt;/p&gt;

&lt;p&gt;But I quickly ran into a problem.&lt;/p&gt;

&lt;p&gt;Real flaky behavior is rarely caused by a single issue.&lt;/p&gt;

&lt;p&gt;Usually it’s a combination of:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;timing dependencies&lt;/li&gt;
&lt;li&gt;complexity&lt;/li&gt;
&lt;li&gt;state mutations&lt;/li&gt;
&lt;li&gt;async interactions&lt;/li&gt;
&lt;li&gt;fixture misuse&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That means simple rule matching eventually hits limits.&lt;/p&gt;

&lt;p&gt;So I added an ML classification layer using CatBoost.&lt;/p&gt;

&lt;p&gt;The pipeline now looks roughly like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Python Test Code ↓ AST Parsing ↓ Feature Extraction ↓ 42-Dimensional Feature Vector ↓ CatBoost Classification ↓ Flaky Probability + Severity
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And honestly, CatBoost turned out to be a surprisingly strong fit.&lt;/p&gt;

&lt;p&gt;Most developers associate CatBoost with recommendation systems or business analytics. But it’s extremely good at structured tabular feature classification.&lt;/p&gt;

&lt;p&gt;Which is exactly what AST-derived metrics become.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The 42-Feature Detection System&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This is where the project became much more than “another linter.”&lt;/p&gt;

&lt;p&gt;FlakyDetector currently extracts a 42-dimensional feature space.&lt;/p&gt;

&lt;p&gt;The features include:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Feature Group       Count&lt;br&gt;
AST Features            16&lt;br&gt;
Category Features   9&lt;br&gt;
Fixture Analysis    5&lt;br&gt;
Derived Metrics         3&lt;br&gt;
Confidence Scores   8&lt;br&gt;
Test Smells&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Examples include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;timing dependency counters&lt;/li&gt;
&lt;li&gt;network interaction detection&lt;/li&gt;
&lt;li&gt;mutation ratios&lt;/li&gt;
&lt;li&gt;fixture scope analysis&lt;/li&gt;
&lt;li&gt;pattern diversity metrics&lt;/li&gt;
&lt;li&gt;cyclomatic complexity scoring&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The system then classifies the probability of flakiness and assigns severity levels.&lt;/p&gt;

&lt;p&gt;But the important part is this:&lt;/p&gt;

&lt;p&gt;The model is explainable.&lt;/p&gt;

&lt;p&gt;That matters a lot in developer tooling.&lt;/p&gt;

&lt;p&gt;Nobody wants a black-box AI saying:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“Your test is dangerous. Trust me.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So FlakyDetector exposes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;confidence levels&lt;/li&gt;
&lt;li&gt;detected anti-patterns&lt;/li&gt;
&lt;li&gt;feature importance&lt;/li&gt;
&lt;li&gt;severity categories&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The goal is not just prediction.&lt;/p&gt;

&lt;p&gt;The goal is understanding.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Architecture: Clean, Fast, and CI-Friendly&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The project follows a Hexagonal Architecture approach.&lt;/p&gt;

&lt;p&gt;That means the core analysis engine stays isolated from:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;UI&lt;/li&gt;
&lt;li&gt;infrastructure&lt;/li&gt;
&lt;li&gt;APIs&lt;/li&gt;
&lt;li&gt;storage layers&lt;/li&gt;
&lt;li&gt;CI integrations&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fokmojankqf6nb4wyi01z.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fokmojankqf6nb4wyi01z.png" alt=" " width="800" height="817"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fwhjc439bhkp8j9jghbxx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fwhjc439bhkp8j9jghbxx.png" alt=" " width="800" height="241"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fhj0z5v5sh57xtbr6xnss.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fhj0z5v5sh57xtbr6xnss.png" alt=" " width="800" height="719"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The stack currently includes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Python 3.12&lt;/li&gt;
&lt;li&gt;FastAPI&lt;/li&gt;
&lt;li&gt;Pydantic v2&lt;/li&gt;
&lt;li&gt;CatBoost&lt;/li&gt;
&lt;li&gt;React + Vite&lt;/li&gt;
&lt;li&gt;ChromaDB&lt;/li&gt;
&lt;li&gt;Ollama&lt;/li&gt;
&lt;li&gt;Docker&lt;/li&gt;
&lt;li&gt;GitHub Actions&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I also focused heavily on developer experience.&lt;/p&gt;

&lt;p&gt;The project uses:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;uv for extremely fast dependency management&lt;/li&gt;
&lt;li&gt;ruff for linting and formatting&lt;/li&gt;
&lt;li&gt;pyright strict typing&lt;/li&gt;
&lt;li&gt;pre-commit&lt;/li&gt;
&lt;li&gt;Dockerized infrastructure&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Because let’s be honest:&lt;/p&gt;

&lt;p&gt;Nobody wants reliability tooling that itself becomes maintenance debt.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;GitHub Actions Integration Is Where It Gets Practical&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This is probably the most important feature for real teams.&lt;/p&gt;

&lt;p&gt;FlakyDetector can block problematic tests directly inside CI pipelines.&lt;/p&gt;

&lt;p&gt;Example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name: Run FlakyDetector run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;uv run python scripts/scan_folder.py ./tests --fail-on-critical&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If the system detects critical anti-patterns, the pipeline fails immediately.&lt;/p&gt;

&lt;p&gt;That means developers catch instability risks during code review instead of after the test suite starts randomly exploding three weeks later.&lt;/p&gt;

&lt;p&gt;This is especially useful for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;fintech platforms&lt;/li&gt;
&lt;li&gt;SaaS systems&lt;/li&gt;
&lt;li&gt;async Python services&lt;/li&gt;
&lt;li&gt;microservice environments&lt;/li&gt;
&lt;li&gt;ML infrastructure&lt;/li&gt;
&lt;li&gt;large monorepos&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;The RAG + LLM Layer Sounds Weird… But It’s Useful&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;One experimental feature I added integrates:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;ChromaDB&lt;/li&gt;
&lt;li&gt;vector search&lt;/li&gt;
&lt;li&gt;local LLMs via Ollama&lt;/li&gt;
&lt;li&gt;semantic instability analysis&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;At first glance it sounds like:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“Congratulations, we added AI to flaky tests.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Which honestly made me laugh too.&lt;/p&gt;

&lt;p&gt;But there’s a practical reason behind it.&lt;/p&gt;

&lt;p&gt;Large repositories often contain repeated instability patterns across multiple teams.&lt;/p&gt;

&lt;p&gt;The semantic search layer allows engineers to find tests with similar architectural problems.&lt;/p&gt;

&lt;p&gt;For example:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“Show me tests similar to this flaky async Redis integration.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That becomes surprisingly powerful in enterprise-scale repositories.&lt;/p&gt;

&lt;p&gt;It’s still evolving, but I think AI-assisted reliability engineering is going to become much more important over the next few years.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why I Think This Problem Matters&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Modern engineering teams invest enormous effort into:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;observability&lt;/li&gt;
&lt;li&gt;security&lt;/li&gt;
&lt;li&gt;performance&lt;/li&gt;
&lt;li&gt;type safety&lt;/li&gt;
&lt;li&gt;infrastructure automation&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But test reliability is still oddly under-engineered.&lt;/p&gt;

&lt;p&gt;We accept flaky tests as “normal.”&lt;/p&gt;

&lt;p&gt;That’s strange if you think about it.&lt;/p&gt;

&lt;p&gt;Because unstable tests don’t just waste CI minutes.&lt;/p&gt;

&lt;p&gt;They quietly destroy confidence in the engineering process itself.&lt;/p&gt;

&lt;p&gt;FlakyDetector is my attempt to treat flaky testing as an architectural problem instead of random chaos.&lt;/p&gt;

&lt;p&gt;And honestly, I think the industry needs more tools that shift reliability checks earlier into the development lifecycle.&lt;/p&gt;

&lt;p&gt;The same way:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;CodeQL changed security scanning&lt;/li&gt;
&lt;li&gt;mypy changed Python typing&lt;/li&gt;
&lt;li&gt;Ruff changed linting performance&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Static reliability analysis could become a completely normal part of CI pipelines.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Try It Yourself&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Quick setup:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/Artem7898/flakydetector &lt;span class="nb"&gt;cd &lt;/span&gt;flakydetector 

uv venv &lt;span class="nt"&gt;--python&lt;/span&gt; 3.12 

&lt;span class="nb"&gt;source&lt;/span&gt; .venv/bin/activate 

uv pip &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="s2"&gt;".[dev]"&lt;/span&gt; 

python scripts/train_model.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Run a scan:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;uv run python scripts/scan_folder.py ./tests/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And yes…&lt;/p&gt;

&lt;p&gt;There’s a good chance it finds something uncomfortable in your test suite.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;One Final Question&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;How many flaky tests are currently sitting in your repository pretending to be “temporary”?&lt;/p&gt;

&lt;p&gt;And how much engineering time are they silently burning every single week?&lt;/p&gt;

&lt;p&gt;That’s probably worth thinking about.&lt;/p&gt;

&lt;p&gt;If this article was useful — follow me for more deep dives into Python backend engineering, CI/CD systems, AST tooling, static analysis, and modern developer infrastructure.&lt;/p&gt;

&lt;p&gt;I’d genuinely love to hear how your team deals with flaky tests today.&lt;/p&gt;

&lt;p&gt;Retry buttons?&lt;br&gt;
Quarantine lists?&lt;br&gt;
Pure denial?&lt;/p&gt;

&lt;p&gt;Write in the comments — I’m curious.&lt;/p&gt;

</description>
      <category>python</category>
      <category>testing</category>
      <category>machinelearning</category>
      <category>devops</category>
    </item>
    <item>
      <title>Django Nova: Bringing Strict Typing and Async-First Architecture to Django Models</title>
      <dc:creator>Artem</dc:creator>
      <pubDate>Mon, 22 Jun 2026 16:59:30 +0000</pubDate>
      <link>https://dev.to/artem7898/django-nova-why-i-rebuilt-djangos-weakest-layer-and-what-problems-it-actually-solves-4bik</link>
      <guid>https://dev.to/artem7898/django-nova-why-i-rebuilt-djangos-weakest-layer-and-what-problems-it-actually-solves-4bik</guid>
      <description>&lt;p&gt;Django is one of those frameworks engineers keep returning to.&lt;/p&gt;

&lt;p&gt;Fast MVPs. Mature ecosystem. Battle-tested ORM. Admin panel that feels like cheating.&lt;/p&gt;

&lt;p&gt;And yet, every experienced Django developer eventually hits the same wall.&lt;/p&gt;

&lt;p&gt;Not performance.&lt;/p&gt;

&lt;p&gt;Not scalability.&lt;/p&gt;

&lt;p&gt;Architecture.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Specifically: type safety, validation duplication, async chaos, and runtime surprises that only appear at 2AM in production when your logs start looking like modern art.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;That frustration is exactly why I built Django Nova.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://pypi.org/project/django-nova/" rel="noopener noreferrer"&gt;PyPI&lt;/a&gt; &lt;br&gt;
&lt;a href="https://github.com/Artem7898/django-nova" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And no — this isn’t “yet another Django helper library.”&lt;/p&gt;

&lt;p&gt;The goal was much more ambitious:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Make Django predictable, typed, async-first, and safe enough for large-scale engineering teams without abandoning Django itself.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Sounds dramatic?&lt;/p&gt;

&lt;p&gt;Maybe.&lt;/p&gt;

&lt;p&gt;But let’s break down why this problem even exists.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Hidden Problem Inside Django Nobody Talks About&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Django was born in 2005.&lt;/p&gt;

&lt;p&gt;Back then, Python didn’t have:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;- typing&lt;/li&gt;
&lt;li&gt;asyncio&lt;/li&gt;
&lt;li&gt;Pydantic&lt;/li&gt;
&lt;li&gt;modern validation systems&lt;/li&gt;
&lt;li&gt;static analysis tooling like Pyright or Ruff&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;The framework evolved, but its core architecture still carries assumptions from a pre-type-hint era.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;And this creates a weird situation.&lt;/p&gt;

&lt;p&gt;Your stack today probably looks like this:&lt;/p&gt;

&lt;p&gt;Django + DRF + Pydantic + Celery + async APIs + mypy&lt;/p&gt;

&lt;p&gt;But internally?&lt;/p&gt;

&lt;p&gt;You’re still fighting:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;duplicated schemas&lt;/li&gt;
&lt;li&gt;weak runtime guarantees&lt;/li&gt;
&lt;li&gt;dynamic model fields&lt;/li&gt;
&lt;li&gt;serializer inconsistencies&lt;/li&gt;
&lt;li&gt;sync/async boundary issues&lt;/li&gt;
&lt;li&gt;hidden ORM side effects&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You validate data in:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Django Forms&lt;/li&gt;
&lt;li&gt;DRF Serializers&lt;/li&gt;
&lt;li&gt;Pydantic models&lt;/li&gt;
&lt;li&gt;database constraints&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Four layers.&lt;/p&gt;

&lt;p&gt;Same data.&lt;/p&gt;

&lt;p&gt;Different logic.&lt;/p&gt;

&lt;p&gt;And eventually they drift apart.&lt;/p&gt;

&lt;p&gt;One field becomes optional in one place but required in another.&lt;/p&gt;

&lt;p&gt;One validator changes but another doesn’t.&lt;/p&gt;

&lt;p&gt;One API silently accepts invalid payloads.&lt;/p&gt;

&lt;p&gt;Congratulations — you’ve created distributed chaos inside a monolith.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;So What Is Django Nova?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;At its core, Django Nova is an async-first typed architecture layer for Django 5+.&lt;/p&gt;

&lt;p&gt;It combines ideas from:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Pydantic v2&lt;/li&gt;
&lt;li&gt;FastAPI&lt;/li&gt;
&lt;li&gt;modern typed Python&lt;/li&gt;
&lt;li&gt;declarative validation systems&lt;/li&gt;
&lt;li&gt;repository/service architectures&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;but keeps Django where Django is strongest:&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;ORM&lt;/li&gt;
&lt;li&gt;migrations&lt;/li&gt;
&lt;li&gt;admin&lt;/li&gt;
&lt;li&gt;ecosystem&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The philosophy is simple:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Keep Django’s productivity. Remove Django’s unpredictability.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That means:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;strongly typed models&lt;/li&gt;
&lt;li&gt;unified validation&lt;/li&gt;
&lt;li&gt;async-compatible workflows&lt;/li&gt;
&lt;li&gt;safer service boundaries&lt;/li&gt;
&lt;li&gt;explicit contracts between layers&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And honestly?&lt;/p&gt;

&lt;p&gt;That changes the developer experience more than people expect.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F28ucgijkyc5jw9nw8y4c.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F28ucgijkyc5jw9nw8y4c.png" alt=" " width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why Validation Duplication Is a Bigger Disaster Than Performance&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Most teams obsess over milliseconds.&lt;/p&gt;

&lt;p&gt;But production incidents usually come from something much simpler:&lt;/p&gt;

&lt;p&gt;Bad data.&lt;/p&gt;

&lt;p&gt;Imagine this payload:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"email"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"not-an-email"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"age"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;-5&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now imagine:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;frontend validates differently&lt;/li&gt;
&lt;li&gt;DRF serializer partially validates&lt;/li&gt;
&lt;li&gt;model allows save()&lt;/li&gt;
&lt;li&gt;Celery task crashes later&lt;/li&gt;
&lt;li&gt;analytics pipeline breaks silently&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;This is how engineering debt grows.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Not with explosions.&lt;/p&gt;

&lt;p&gt;With tiny inconsistencies.&lt;/p&gt;

&lt;p&gt;Django Nova uses a unified validation pipeline inspired by Pydantic v2’s strict parsing model.&lt;/p&gt;

&lt;p&gt;Instead of scattering validation everywhere, you define contracts once.&lt;/p&gt;

&lt;p&gt;Example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;UserCreate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Schema&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt; &lt;span class="n"&gt;age&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt; &lt;span class="nd"&gt;@field_validator&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;age&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;validate_age&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cls&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="nc"&gt;ValueError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Age must be positive&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now validation becomes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;reusable&lt;/li&gt;
&lt;li&gt;typed&lt;/li&gt;
&lt;li&gt;deterministic&lt;/li&gt;
&lt;li&gt;IDE-friendly&lt;/li&gt;
&lt;li&gt;testable&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And yes, your autocomplete suddenly feels like magic.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Under the Hood: How Django Nova Actually Works&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This is where things get interesting.&lt;/p&gt;

&lt;p&gt;Django Nova isn’t trying to replace Django ORM.&lt;/p&gt;

&lt;p&gt;That would be pointless.&lt;/p&gt;

&lt;p&gt;Instead, it wraps Django’s weakest architectural seams with stricter abstractions.&lt;/p&gt;

&lt;p&gt;The project focuses on:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;1. Typed schemas&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Inspired by Pydantic v2 internals.&lt;/p&gt;

&lt;p&gt;Instead of dynamic serializer behavior, Nova introduces explicit contracts between:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;API layer&lt;/li&gt;
&lt;li&gt;services&lt;/li&gt;
&lt;li&gt;ORM&lt;/li&gt;
&lt;li&gt;background jobs&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This dramatically reduces runtime ambiguity.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;2. Async-first architecture&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Django added async support gradually.&lt;/p&gt;

&lt;p&gt;But anyone who has mixed sync ORM calls with async views knows the pain:&lt;/p&gt;

&lt;p&gt;SynchronousOnlyOperation&lt;/p&gt;

&lt;p&gt;The classic “surprise, you touched the database wrong” moment.&lt;/p&gt;

&lt;p&gt;Nova encourages explicit async boundaries and cleaner async orchestration patterns.&lt;/p&gt;

&lt;p&gt;That matters because modern apps increasingly rely on:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;WebSockets&lt;/li&gt;
&lt;li&gt;streaming APIs&lt;/li&gt;
&lt;li&gt;AI inference&lt;/li&gt;
&lt;li&gt;event-driven systems&lt;/li&gt;
&lt;li&gt;real-time dashboards&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Async is no longer “optional future architecture.”&lt;/p&gt;

&lt;p&gt;It’s normal backend engineering.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;3. Service-oriented structure&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Typical Django apps become “fat models + mystery utils.py.”&lt;/p&gt;

&lt;p&gt;Nova pushes projects toward explicit service layers:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;UserService.create_user() PaymentService.capture() OrderService.complete()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This sounds boring until your project reaches 100k+ LOC.&lt;/p&gt;

&lt;p&gt;Then suddenly architecture matters more than syntax.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Performance? Yes, That Too&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Let’s talk numbers.&lt;/p&gt;

&lt;p&gt;One misconception about typed systems is that they’re “slow.”&lt;/p&gt;

&lt;p&gt;Actually, modern typed validation engines can outperform traditional serializer-heavy pipelines because they:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;avoid excessive dynamic introspection&lt;/li&gt;
&lt;li&gt;reduce runtime ambiguity&lt;/li&gt;
&lt;li&gt;optimize parsing paths&lt;/li&gt;
&lt;li&gt;leverage compiled validation internals&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Especially with Python 3.12+, the gap becomes noticeable.&lt;/p&gt;

&lt;p&gt;Django Nova targets:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Python 3.12+&lt;/li&gt;
&lt;li&gt;Django 5+&lt;/li&gt;
&lt;li&gt;async-native workflows&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Meaning it’s built for modern CPython optimizations from day one.&lt;/p&gt;

&lt;p&gt;And unlike many “enterprise abstractions,” it doesn’t require rewriting your entire stack.&lt;/p&gt;

&lt;p&gt;You can introduce it incrementally.&lt;/p&gt;

&lt;p&gt;Which is probably the only reason developers will actually adopt it.&lt;/p&gt;

&lt;p&gt;Because let’s be honest:&lt;/p&gt;

&lt;p&gt;Nobody wants another “complete rewrite migration strategy.”&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Where Django Nova Fits in the Market&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This is the interesting part.&lt;/p&gt;

&lt;p&gt;Django Nova sits somewhere between:&lt;/p&gt;

&lt;p&gt;Framework           Philosophy&lt;br&gt;
Django REST Framework   flexible but highly dynamic&lt;br&gt;
FastAPI                 typed and async-first&lt;br&gt;
Pydantic            validation-focused&lt;br&gt;
Django Ninja            API ergonomics&lt;br&gt;
Litestar            modern async architecture &lt;/p&gt;

&lt;p&gt;Nova’s niche is different.&lt;/p&gt;

&lt;p&gt;It’s not trying to replace Django with a new framework.&lt;/p&gt;

&lt;p&gt;It’s trying to modernize Django’s engineering model itself.&lt;/p&gt;

&lt;p&gt;That distinction matters.&lt;/p&gt;

&lt;p&gt;Because many companies want Django:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;mature ecosystem&lt;/li&gt;
&lt;li&gt;stable ORM&lt;/li&gt;
&lt;li&gt;admin panel&lt;/li&gt;
&lt;li&gt;hiring availability&lt;/li&gt;
&lt;li&gt;documentation&lt;/li&gt;
&lt;li&gt;deployment simplicity&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But they also want:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;typing&lt;/li&gt;
&lt;li&gt;async workflows&lt;/li&gt;
&lt;li&gt;cleaner contracts&lt;/li&gt;
&lt;li&gt;safer large-team development&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Nova tries to bridge that gap.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A Real-World Use Case&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Imagine you’re building:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;crypto exchange backend&lt;/li&gt;
&lt;li&gt;fintech APIs&lt;/li&gt;
&lt;li&gt;AI orchestration platform&lt;/li&gt;
&lt;li&gt;ERP system&lt;/li&gt;
&lt;li&gt;marketplace&lt;/li&gt;
&lt;li&gt;high-volume SaaS&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now imagine 15 developers touching the same models.&lt;/p&gt;

&lt;p&gt;Without strict contracts, entropy appears fast.&lt;/p&gt;

&lt;p&gt;One service expects:&lt;/p&gt;

&lt;p&gt;Decimal&lt;/p&gt;

&lt;p&gt;Another passes:&lt;/p&gt;

&lt;p&gt;float&lt;/p&gt;

&lt;p&gt;One async task mutates state unexpectedly.&lt;/p&gt;

&lt;p&gt;One serializer silently casts types.&lt;/p&gt;

&lt;p&gt;Three months later?&lt;/p&gt;

&lt;p&gt;Nobody trusts production behavior anymore.&lt;/p&gt;

&lt;p&gt;Django Nova exists to reduce that uncertainty.&lt;/p&gt;

&lt;p&gt;Not through “magic.”&lt;/p&gt;

&lt;p&gt;Through stricter architecture.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why This Matters More in the AI Era&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Here’s something people underestimate.&lt;/p&gt;

&lt;p&gt;AI systems amplify bad backend architecture.&lt;/p&gt;

&lt;p&gt;LLMs generate unpredictable payloads.&lt;/p&gt;

&lt;p&gt;Agents call APIs dynamically.&lt;/p&gt;

&lt;p&gt;Event streams become noisy.&lt;/p&gt;

&lt;p&gt;Suddenly validation quality matters a lot.&lt;/p&gt;

&lt;p&gt;Typed contracts stop being “nice engineering aesthetics.”&lt;/p&gt;

&lt;p&gt;They become survival tools.&lt;/p&gt;

&lt;p&gt;That’s one reason modern backend engineering is moving toward:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;schema-first design&lt;/li&gt;
&lt;li&gt;typed APIs&lt;/li&gt;
&lt;li&gt;explicit contracts&lt;/li&gt;
&lt;li&gt;deterministic validation&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Nova follows that trend directly.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Most Important Part: Developer Experience&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This might sound silly, but good architecture changes how coding feels.&lt;/p&gt;

&lt;p&gt;You stop guessing.&lt;/p&gt;

&lt;p&gt;You stop checking documentation every 10 minutes.&lt;/p&gt;

&lt;p&gt;Your IDE becomes useful instead of decorative.&lt;/p&gt;

&lt;p&gt;Refactors become safer.&lt;/p&gt;

&lt;p&gt;Autocomplete becomes smarter.&lt;/p&gt;

&lt;p&gt;Runtime bugs move into editor-time feedback.&lt;/p&gt;

&lt;p&gt;And yes — that’s a huge productivity upgrade.&lt;/p&gt;

&lt;p&gt;Especially for teams.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Open Source, GitHub, and Why Stars Actually Matter&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Django Nova is fully open source.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/Artem7898/django-nova" rel="noopener noreferrer"&gt;GitHub:&lt;/a&gt;&lt;br&gt;
&lt;a href="https://pypi.org/project/django-nova/" rel="noopener noreferrer"&gt;PyPI:&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And honestly?&lt;/p&gt;

&lt;p&gt;Open source projects live or die from community momentum.&lt;/p&gt;

&lt;p&gt;A GitHub star sounds trivial, but it affects:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;visibility&lt;/li&gt;
&lt;li&gt;contributors&lt;/li&gt;
&lt;li&gt;ecosystem trust&lt;/li&gt;
&lt;li&gt;adoption&lt;/li&gt;
&lt;li&gt;maintainer motivation&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So if the architecture resonates with you:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;give the repo a star&lt;/li&gt;
&lt;li&gt;open issues&lt;/li&gt;
&lt;li&gt;contribute code&lt;/li&gt;
&lt;li&gt;benchmark it&lt;/li&gt;
&lt;li&gt;challenge design decisions&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That’s how strong engineering ecosystems are built.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Where This Could Go Next&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The most exciting future for Django probably isn’t replacing it.&lt;/p&gt;

&lt;p&gt;It’s evolving it.&lt;/p&gt;

&lt;p&gt;Over the next few years, I expect the Python backend ecosystem to move heavily toward:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;stricter typing&lt;/li&gt;
&lt;li&gt;async-native architectures&lt;/li&gt;
&lt;li&gt;schema-driven systems&lt;/li&gt;
&lt;li&gt;compile-time guarantees&lt;/li&gt;
&lt;li&gt;service-oriented monoliths&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Frameworks that ignore this trend may slowly become harder to scale organizationally.&lt;/p&gt;

&lt;p&gt;Not technically.&lt;/p&gt;

&lt;p&gt;Humanly.&lt;/p&gt;

&lt;p&gt;Because modern engineering complexity is less about servers…&lt;/p&gt;

&lt;p&gt;…and more about coordination between developers.&lt;/p&gt;

&lt;p&gt;That’s the real scalability problem.&lt;/p&gt;

&lt;p&gt;And typed architecture helps solve it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Final Thought&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Django made web development accessible.&lt;/p&gt;

&lt;p&gt;But modern backend systems demand stronger guarantees than Django originally provided.&lt;/p&gt;

&lt;p&gt;Django Nova is my attempt to close that gap without sacrificing what made Django great in the first place.&lt;/p&gt;

&lt;p&gt;The real question isn’t:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“Do we need more tooling?”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It’s:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“Can large Python systems stay maintainable without stronger contracts?”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I think the answer is becoming obvious.&lt;/p&gt;

&lt;p&gt;What do you think?&lt;/p&gt;

&lt;p&gt;Would you adopt a typed async-first architecture layer inside Django — or do you prefer keeping Django максимально flexible and dynamic?&lt;/p&gt;

&lt;p&gt;I’m genuinely curious how teams are solving this today.&lt;/p&gt;

&lt;p&gt;🙌 If this article was useful — follow for more deep technical breakdowns.&lt;br&gt;
Leave a comment if you’ve faced similar problems in Django architecture.&lt;br&gt;
And if the project looks interesting, consider starring the repo or contributing on GitHub — it genuinely helps the project grow.&lt;/p&gt;

</description>
      <category>django</category>
      <category>python</category>
      <category>webdev</category>
      <category>opensource</category>
    </item>
  </channel>
</rss>
