A high-traffic Italian editorial portal can run entirely on open-source software, with not a single commercial product in the publishing stack. I have been watching this at close range on the Radio 105 group sites — 105.net, radiomontecarlo.net, unitedmusic.it — where peaks track the live broadcast and content changes within minutes. Underneath sits Zope — the Z Object Publishing Environment — with Python as the application language, distributed under the Zope Public License.

Context

In 2001 the dominant pattern for editorial sites is still the page generated by a script that queries a relational database and stitches HTML together. It works, but it carries a familiar problem with it: every request rebuilds, from scratch, a structure that is in fact an object graph — sections, programmes, cards, schedule blocks — forced flat into rows and columns. For a site that publishes dozens of times a day, the distance between how the editor thinks (containers inside containers) and how the database is built (tables) becomes daily friction.

Zope inverts the starting point. Content lives in ZODB, Zope’s transactional object database: objects are persistent by default, you walk them by URL like a filesystem, and the hierarchy I read in the URL is the same one that exists in memory. A programmes folder holding card objects is not serialised and reassembled on each hit — it is already there, reachable by path.

Architecture

Three mechanisms carry a portal like this in practice.

The first is acquisition. In Zope an object inherits by context: a card under /rmc/programmes/ can call a header method defined at the root without knowing where it sits, because Zope walks up the containment hierarchy until it meets it. In the newsroom this means writing layout, navigation and shared fragments once, near the top, and letting every sub-section pick them up. Adding a section does not force you to rewire the templates: the new object takes what it needs from its container.

The second is the separation of logic from presentation through templates. Zope’s historic language is DTML, a tag syntax that interleaves control flow with markup; convenient, but it produces documents that are not valid HTML and that a visual editor cannot open. Zope Page Templates, introduced with Zope 2.3, move the control into attributes in the TAL namespace (Template Attribute Language): the file stays well-formed HTML, and a tal:repeat or a tal:content sits beside the markup rather than inside it. A sub-editor working on a schedule opens the template in a visual editor and sees it render, without tripping over logic tags.

The third is through-the-web management. The whole instance is administered from the browser: creating objects, editing methods and templates, assigning permissions all happen from an authenticated web interface, with a role-based security model applied object by object. In a distributed newsroom, where the person curating a programme is not the person running the server, being able to assign fine-grained per-branch permissions weighs more than any amount of performance.

The critical knot

The real knot in a radio portal is read load. During a live broadcast thousands of requests land on a handful of hot pages — the home, the card for the programme on air, the competition page — while writes stay rare and concentrated (the editor updating). A single Zope process on ZODB has a ceiling: the database is built for many reads and few writes, but one server remains a CPU bottleneck.

The answer in the stack is ZEO — Zope Enterprise Objects. ZEO splits database access into client and server: a single ZEO Storage Server holds the storage, and several Zope processes connect to it as clients, sharing the same database at every instant. In practice I put several Zope processes (on the same machine or on different ones) behind a balancer, all reading the same ZODB through ZEO. Reads scale horizontally by adding clients; writes stay serialised on the server, and that is exactly how the load of an editorial site should be distributed. ZEO is Python code speaking TCP/IP, and it adds a storage type, ClientStorage, that forwards calls to the server: for the application the difference is transparent, because a ZEO client behaves like a local storage.

Implications

What interests me here is not Zope as such, it is that an open-source stack carries a mission-critical Italian case made of real traffic and editorial deadlines. Three concrete consequences.

The first is about cost and lock-in: the whole publishing chain — application server, object database, language, template engine — is inspectable and modifiable, with no per-CPU licences and no roadmap dictated by a vendor. The second is about skills: whoever maintains the site programmes in Python, a general-purpose language, not in a proprietary dialect locked inside the product. The third is about the data model: treating the site as a graph of persistent objects, rather than as queries against tables, brings the structure of the code closer to the editorial structure of the content, and reduces the mental steps needed to get from one to the other.

The ad hoc development of the Radio 105 group portals on this stack is documented in the noze insight: https://www.noze.it/en/insights/radio-105-portals/.

Limits

ZODB is no panacea. The persistent-object model complicates the queries a relational database resolves with a JOIN: finding “every card published last month with a given tag” requires building and maintaining indexes by hand (in Zope, a Catalog), because there is no SQL to lean on. ZODB’s default storage, FileStorage, grows append-only and must be compacted (pack) from time to time, or the Data.fs file swells without bound. ZEO scales reads, but the storage server stays a single point to watch. And the learning curve is steep: acquisition and through-the-web management give power, yet anyone arriving from CGI and SQL has to unlearn a few habits before moving with any ease. These are acceptable trade-offs for a read-heavy, write-light portal; they would be less so for a transactional application dominated by analytical queries.


https://www.python.org/ https://www.zope.org/

Cover image: Radio broadcasting studio with a transmission console, audio mixer and microphone on a boom arm — photo by Henryk Kotowski, CC BY 2.5 — https://commons.wikimedia.org/wiki/File:Radio_syd_2000_studio.jpg