Semantic Systems / Language / Glyphs
01-durable-ai-publication-orchestration-and-recovery.md
Report summary
This research report establishes a comprehensive architectural framework for orchestrating long-running, asynchronous artificial intelligence publication workflows within modestly hosted web environments. Commissioned for InternationalIntelligence.org, the analysis specifically addresses the systemi
Key topics
- Semantic Systems / Language / Glyphs
- Semantic Systems
- Language
- Glyphs
- AI
- Agentic Web
- SQL
- TypeScript
- Python
Research provenance
For citation, use the report title and canonical URL. Archival presence does not establish authorship or promote report statements into portfolio evidence.
This page renders the archived Markdown as safe, formatted HTML. It is background research and does not become a portfolio claim without evidence review.
Full report
On this page
1. Executive Summary
This research report establishes a comprehensive architectural framework for orchestrating long-running, asynchronous artificial intelligence publication workflows within modestly hosted web environments. Commissioned for InternationalIntelligence.org, the analysis specifically addresses the systemic vulnerabilities inherent in orchestrating remote asynchronous processing—such as the OpenAI Responses API—within a standard PHP 8.x and LiteSpeed/PHP-FPM infrastructure. The research resolves a known critical failure pattern where accepted provider work becomes stranded, duplicated, or lost due to exhausted local polling budgets, ambiguous timeouts, and the absence of durable wakeup mechanisms. The analysis yields five primary architectural conclusions:
1. Strict Decoupling of Generation and Polling Budgets: A robust system cannot safely conflate the operational budget for creating a remote job with the budget for monitoring it. Generation attempts and continuation polls must operate on strictly isolated tracking mechanisms. Exhausting a polling budget must transition the job to a durable delayed-recovery state, never to an aborted state that erroneously permits a duplicate generation attempt, which would risk duplicate financial expenditure and data corruption.
2. Mandatory Application of Fencing Tokens Over Time-Based Leases: Distributed locking mechanisms based solely on time-to-live (TTL) expirations are provably unsafe in non-deterministic execution environments like PHP, which are subject to garbage collection pauses, execution timeouts (max\_execution\_time), and detached processes (ignore\_user\_abort)1. Exactly-once consumption guarantees require database-enforced monotonic fencing tokens (optimistic concurrency control) validated at the precise moment of state mutation3.
3. The Ambiguous Timeout Requires Local Quarantine and Deduplication: When an HTTP connection drops during the creation phase before a provider response identifier is returned, the local system operates under critical uncertainty. Because standard APIs often lack documented strict idempotency keys for asynchronous completions, the architecture must quarantine the ambiguous intent. It must enforce strict exactly-once publication constraints downstream via a composite unique local key, shifting deduplication authority from the network edge to the local relational database5.
4. Decoupling Provider Completion from Publication Finality: A provider status indicating completion merely signifies that the remote computation has finished and the artifact is temporarily available (typically for 10 minutes in background execution modes)6. It does not indicate that the publication is durable. The architecture must explicitly model the intermediate states where data is fetched, deterministically validated, and secured locally before any publication actions are authorized.
5. Transactional Outbox for Eventual Consistency: To achieve atomic transitions between the database state and external visibility (e.g., publishing to a static site, search index, or content delivery network), the system must utilize the Transactional Outbox pattern7. The local database transaction commits both the edition payload and an outbox event, delegating the non-transactional network publication to a separate, idempotent background worker.
2. Explicit Assumptions and Exclusions
The architectural deductions formulated herein are bounded by specific environmental constraints and exclusions. Assumptions:
- The deployment environment consists of a standard Linux, Apache/LiteSpeed, MySQL/MariaDB, and PHP (LAMP/LEMP) stack. The architecture must not assume the presence of Kubernetes, Apache Kafka, dedicated distributed workflow engines (e.g., Temporal), or a full-time site reliability engineering (SRE) team.
- The system utilizes remote asynchronous processing, modeled primarily on the OpenAI Responses API in background: true mode. This mode retains response data temporarily (roughly 10 minutes) to enable polling, even when Zero Data Retention (ZDR) via store: false is active6.
- The local system acts as the absolute authority for time, state mapping, URL generation, deterministic validation, and the final publication lifecycle.
- Background jobs may be triggered by system cron schedulers, hosting-panel chronometers, or opportunistic browser wakeups.
- Concurrency hazards are assumed to be present due to concurrent language route triggers (e.g., English and Spanish processing tracks) and overlapping scheduler executions.
Exclusions:
- This analysis excludes the evaluation of alternative Large Language Models (LLMs), prompt engineering strategies, or model quality assessments. The architectural patterns focus strictly on standardizing asynchronous HTTP interactions and ensuring durable execution.
- The report does not cover the frontend User Interface (UI) or User Experience (UX) for editorial staff, focusing purely on backend orchestration, state persistence, and recovery mechanics.
- General physical infrastructure security, network-level Distributed Denial of Service (DDoS) mitigation, and Web Application Firewall (WAF) tuning fall outside the purview of this specific orchestration design.
3. Research Basis and Source Hierarchy
The research relies on primary technical documentation, API specifications, and peer-reviewed distributed systems literature. The temporal boundary for all technological assertions is restricted to July 31, 2026, 02:38:05 UTC. Source Hierarchy:
1. Primary Provider Documentation: Official OpenAI API references, Responses API guides, background mode documentation, and error-handling specifications formulate the baseline constraints for remote interactions6.
2. Distributed Systems Literature: Academic papers and established theoretical frameworks concerning distributed consensus, long-lived sagas (Garcia-Molina and Salem)12, fencing tokens and distributed locking (Kleppmann)3, and the Transactional Outbox pattern provide the theoretical foundation for local consistency7.
3. Web Infrastructure Specifications: LiteSpeed Application Programming Interface (LSAPI) documentation, PHP FastCGI Process Manager (FPM) behaviors, and relational database transactional isolation semantics dictate the boundaries of the execution environment1.
4. Standardization Protocols: The Standard Webhooks specification informs the requirements for cryptographic signature verification, constant-time comparison, and replay prevention mechanisms17.
Where vendor documentation exhibits ambiguity—such as the precise retention guarantees of internal orchestration queues or undocumented idempotency behaviors on specific endpoints—conservative engineering principles, including bounded retries, deterministic local state precedence, and pessimistic quarantine protocols, are applied.
4. Canonical Job-State Model
To guarantee that long-running AI publication jobs do not become stranded, duplicated, or silently abandoned, the system requires a high-resolution, canonical state machine mapped to a durable relational database table. Distributed systems lacking explicit state modeling inevitably rely on implicit assumptions derived from log files or shared memory, which disintegrate during process crashes or network partitions19. The architecture mandates the representation of the following 18 distinct states.
4.1 State Definitions and Lifecycle Semantics
The lifecycle of an asynchronous publication job traverses multiple conceptual phases: initialization, remote execution, local recovery, validation, composition, and terminal cleanup.
- NO\_JOB: The baseline system state. A scheduled target exists (e.g., Daily Brief for a specific date), but no processing record has been instantiated in the database.
- CREATE\_ELIGIBLE: A job record is durably committed to the local database with a unique local\_job\_id. All prerequisites are met, the configuration fingerprint is calculated, and the system is authorized to initiate an external provider request.
- CREATE\_IN\_FLIGHT: The HTTP POST request to the provider has been opened, but no response has been received. This state is critical for detecting the Two-Generals Problem equivalent: ambiguous network timeouts5.
- ACCEPTED: The provider has returned an HTTP 200/202, and the response\_id has been safely committed to the local database. The generation budget is formally expended.
- QUEUED: The provider indicates the task is in the remote queue. Local polling budgets begin tracking.
- IN\_PROGRESS: The provider indicates active computation is occurring on their infrastructure11.
- COMPLETED\_NOT\_RETRIEVED: The provider status is completed, but the payload resides exclusively on the remote server. It has not yet been fetched and durably saved to the local database. This state is highly sensitive due to the roughly 10-minute temporary retention window associated with background requests6.
- RETRIEVED\_NOT\_VALIDATED: The payload resides safely in local storage, fully insulating the system from provider-side data expiration policies. The remote provider job is functionally resolved.
- VALIDATION\_FAILED\_RETAINED: The payload failed deterministic local validation (e.g., hallucinated URLs, schema mismatch, or content policy violations). The material is retained locally to prevent repeated financial expenditure on generating identical known-bad output, satisfying the saga pattern's requirement for compensating transaction boundaries12.
- READY\_TO\_COMPOSE: The output has passed all deterministic validation checks and is staged for the final bilingual composition phase.
- COMPOSED\_NOT\_SAVED: The localized (e.g., English and Spanish) outputs have been generated in memory but have not yet been written to the final persistence layer.
- SAVED\_NOT\_PUBLIC: The final edition is stored in the database but lacks the necessary flags, outbox events, or cache invalidations required to be visible to readers.
- PUBLISHED: The terminal success state from the reader's perspective. The edition is live, immutable, and globally visible.
- CLEANUP\_PENDING: The local workflow is complete, but terminal cleanup commands (e.g., deleting remote files, canceling residual streams, or purging temporary data) must be dispatched to the provider to maintain hygiene and compliance.
- DELETED: Terminal cleanup is complete. The lifecycle is fully terminated.
- PROVIDER\_EXPIRED\_OR\_MISSING: Polling resulted in an HTTP 404 or an expiration error from the provider. The remote work is lost and must be triaged by the local recovery engine.
- QUARANTINED: An unrecoverable error, an ambiguous timeout, or the exhaustion of the retry/polling budget has parked the job. It requires human operator intervention or advanced algorithmic reconciliation.
- MANUALLY\_SUSPENDED: An operator has explicitly paused the job to prevent further scheduler iterations or concurrency races during an active incident.
5. State-Transition Mechanics
State transitions within the database must strictly dictate which actions are monotonic (forward-only, never reversing), which may be safely retried without side effects, and which represent terminal conditions. Allowing arbitrary state regression compromises the integrity of the publication and risks duplicate consumption3.
| Current State | Target State | Trigger Event | Allowed Retries | Monotonicity |
|---|---|---|---|---|
| NO\_JOB | CREATE\_ELIGIBLE | Intent received, lock acquired. | N/A | Monotonic |
| CREATE\_ELIGIBLE | CREATE\_IN\_FLIGHT | Pre-flight network initiation. | Yes (if no HTTP sent) | Retriable |
| CREATE\_IN\_FLIGHT | ACCEPTED | HTTP 200/202 with response\_id. | 0 (Must not retry creation) | Monotonic |
| CREATE\_IN\_FLIGHT | QUARANTINED | Connection timeout, no response\_id. | N/A | Terminal (Manual) |
| ACCEPTED | QUEUED / IN\_PROGRESS | Background poll returns status. | Infinite (within SLA) | Retriable |
| QUEUED / IN\_PROGRESS | COMPLETED\_NOT\_RETRIEVED | Poll returns completed. | Infinite (until fetched) | Monotonic |
| COMPLETED\_NOT\_RETRIEVED | RETRIEVED\_NOT\_VALIDATED | Payload downloaded & saved locally. | Yes (Idempotent upsert) | Monotonic |
| RETRIEVED\_NOT\_VALIDATED | READY\_TO\_COMPOSE | Deterministic parsing succeeds. | Yes (Deterministic) | Monotonic |
| RETRIEVED\_NOT\_VALIDATED | VALIDATION\_FAILED\_RETAINED | Deterministic parsing fails. | 0 | Terminal (Repairable) |
| READY\_TO\_COMPOSE | COMPOSED\_NOT\_SAVED | Composition logic executes. | Yes | Retriable |
| COMPOSED\_NOT\_SAVED | SAVED\_NOT\_PUBLIC | DB transaction commits. | Yes (Idempotent update) | Monotonic |
| SAVED\_NOT\_PUBLIC | PUBLISHED | Outbox processor updates cache/feed. | Yes | Monotonic |
| PUBLISHED | CLEANUP\_PENDING | Trigger post-publish tasks. | N/A | Monotonic |
| CLEANUP\_PENDING | DELETED | Provider returns 200 OK on delete. | Yes | Monotonic |
| Any Polling State | PROVIDER\_EXPIRED\_OR\_MISSING | Provider returns 404 or expired. | 0 | Terminal |
6. Architectural Diagrams
The following diagrams illustrate the precise progression of states and the interactions between the local PHP worker daemon, the relational database, and the remote artificial intelligence provider.
6.1 Canonical State Diagram
Code snippet stateDiagram-v2 \[\*\] \--\> NO\_JOB NO\_JOB \--\> CREATE\_ELIGIBLE : Intent received CREATE\_ELIGIBLE \--\> CREATE\_IN\_FLIGHT : Dispatch HTTP POST
CREATE\_IN\_FLIGHT \--\> ACCEPTED : HTTP 200 (response\_id) CREATE\_IN\_FLIGHT \--\> QUARANTINED : Ambiguous Timeout (Network Drop)
ACCEPTED \--\> QUEUED : Poll QUEUED \--\> IN\_PROGRESS : Poll IN\_PROGRESS \--\> COMPLETED\_NOT\_RETRIEVED : Poll
COMPLETED\_NOT\_RETRIEVED \--\> RETRIEVED\_NOT\_VALIDATED : Fetch Payload COMPLETED\_NOT\_RETRIEVED \--\> PROVIDER\_EXPIRED\_OR\_MISSING : 10m TTL Expiry
RETRIEVED\_NOT\_VALIDATED \--\> READY\_TO\_COMPOSE : Validation Pass RETRIEVED\_NOT\_VALIDATED \--\> VALIDATION\_FAILED\_RETAINED : Validation Fail
READY\_TO\_COMPOSE \--\> COMPOSED\_NOT\_SAVED : Compose COMPOSED\_NOT\_SAVED \--\> SAVED\_NOT\_PUBLIC : DB Commit SAVED\_NOT\_PUBLIC \--\> PUBLISHED : Outbox Trigger
PUBLISHED \--\> CLEANUP\_PENDING CLEANUP\_PENDING \--\> DELETED DELETED \--\> \[\*\]
6.2 Sequence: Ordinary Successful Lifecycle
This sequence demonstrates a pristine execution path, highlighting the application of fencing tokens at every database interaction to ensure strict serialization of operations.
Code snippet sequenceDiagram participant Cron as Worker (PHP) participant DB as Local Database participant API as OpenAI API
Cron-\>\>DB: Acquire lease (Fencing Token N) DB--\>\>Cron: Lease Granted, State=CREATE\_ELIGIBLE Cron-\>\>DB: Update State=CREATE\_IN\_FLIGHT Cron-\>\>API: POST /v1/responses (background: true) API--\>\>Cron: HTTP 200, response\_id=123, status=in\_progress Cron-\>\>DB: Update State=ACCEPTED, response\_id=123, Token=N
loop Every 60s (Polling Budget) Cron-\>\>DB: Acquire lease (Fencing Token N+1) Cron-\>\>API: GET /v1/responses/123 API--\>\>Cron: status=completed Cron-\>\>DB: Update State=COMPLETED\_NOT\_RETRIEVED end
Cron-\>\>DB: Acquire lease (Fencing Token N+2) Cron-\>\>API: GET /v1/responses/123 (fetch payload) API--\>\>Cron: JSON payload Cron-\>\>DB: Save payload, State=RETRIEVED\_NOT\_VALIDATED, Token=N+2
Cron-\>\>Cron: Validate and Compose Cron-\>\>DB: Begin Tx Cron-\>\>DB: Save Edition, State=PUBLISHED, Token=N+2 Cron-\>\>DB: Commit Tx
Cron-\>\>API: DELETE /v1/responses/123
6.3 Sequence: Create-Time Ambiguous Timeout
This sequence models the most dangerous failure mode in distributed communication: the system dispatches a command but loses connectivity before the provider can acknowledge receipt5.
Code snippet sequenceDiagram participant Cron as Worker (PHP) participant DB as Local Database participant API as OpenAI API
Cron-\>\>DB: Acquire lease (Token N) Cron-\>\>DB: Update State=CREATE\_IN\_FLIGHT Cron-\>\>API: POST /v1/responses (background: true) Note over Cron,API: Network connection drops during response API--\>\>Cron: Connection Timeout (No response\_id)
Cron-\>\>DB: Update State=QUARANTINED, Error=AmbiguousTimeout, Token=N Note over DB: Job halted. Requires operator review or reconciliation logic to prevent dual billing.
6.4 Sequence: Completed-Response Recovery After Scheduler Outage
This sequence illustrates resilience against local infrastructure degradation, such as the cron daemon crashing, resulting in the expiration of the provider's short-lived background retention window.
Code snippet sequenceDiagram participant Cron as Worker (PHP) participant DB as Local Database participant API as OpenAI API
Note over Cron: Cron daemon crashes for 4 hours Note over API: Job finishes, stays in API memory for \~10m, then expires.
Note over Cron: Cron daemon recovers Cron-\>\>DB: Acquire lease for stale job (Token N+5) DB--\>\>Cron: State=IN\_PROGRESS (Stale) Cron-\>\>API: GET /v1/responses/123 API--\>\>Cron: HTTP 404 / Expired Cron-\>\>DB: Update State=PROVIDER\_EXPIRED\_OR\_MISSING, Token=N+5 Note over Cron,DB: Automated recovery triggers a new job generation under a new local\_job\_id
7. Budgets, Polling, and Backoff Mechanics
A fundamental flaw in naive orchestration is the conflation of the budget to initiate work with the budget to observe work. The architecture must strictly separate these concerns to prevent stranding paid-for processing cycles22.
7.1 Budget Separation
- Generation Budget (generation\_attempts): This budget controls financial expenditure. It is capped strictly (e.g., maximum 3 attempts) and is incremented only when transitioning from CREATE\_ELIGIBLE to CREATE\_IN\_FLIGHT.
- Poll Budget (poll\_attempts): This budget tracks observation frequency. It is capped highly (e.g., 30 attempts, equating to roughly 30 minutes of observation) and increments only when executing GET /responses/{id} against an already ACCEPTED response.
Polling an accepted response constitutes a read operation and consumes negligible API capacity. Treating a slow provider queue as a reason to increment the generation budget causes systems to abandon expensive AI work merely because the provider was momentarily congested. If poll\_attempts exceeds the threshold, the job is transitioned to QUARANTINED—pausing active monitoring but preserving the response\_id so that an operator can manually fetch the result once provider latency subsides.
7.2 Rate Limit Mitigation (HTTP 429 and 500)
When integrating with provider APIs, rate limits (HTTP 429\) and transient server errors (HTTP 500\) are inevitable operational conditions, not fatal exceptions10. The OpenAI API transmits crucial telemetry via HTTP headers such as x-ratelimit-reset and x-ratelimit-remaining24. The architecture dictates a three-tiered approach to backoff:
1. Header Precedence: If the provider emits a retry-after or x-ratelimit-reset header specifying a wait time (e.g., 45 seconds), the local system extracts this timestamp and updates the lease\_expiry to match. The job is placed in a sleep state precisely until the provider indicates capacity is restored26.
2. Exponential Backoff with Jitter: In the absence of explicit headers, the system defaults to exponential backoff (e.g., 2s, 4s, 8s, 16s). Crucially, randomized jitter (±20%) is applied to the delay. This prevents the "Thundering Herd" phenomenon, wherein dozens of blocked background jobs wake up simultaneously, instantly triggering another rate limit violation27.
3. Escalation vs. Termination: Exhausting a backoff sequence during a poll does not cancel the remote job. It merely suspends local observation, ensuring the remote processing continues uninterrupted.
8. Idempotency, Identifiers, and Ambiguity
Distributed systems theory dictates that exactly-once network delivery over unreliable channels is impossible. Network packets will be lost, dropped, or duplicated. Consequently, the application layer must assume responsibility for idempotency5.
8.1 The Create-Time Ambiguous Timeout
The most challenging edge case occurs when the local system transmits the POST request to generate a new edition, but the TCP connection drops before the provider can return the response\_id. The provider may have received the request and begun processing (costing money), or the packet may have died in transit. While certain OpenAI endpoints (such as Commerce and Ads) support an explicit Idempotency-Key header to safely retry requests without duplication28, the standard Responses API lacks documented guarantees for strict idempotency keys on general completions. Architectural Resolution: The local database acts as the ultimate authority for deduplication. A composite unique key—comprising (edition\_date, channel, language)—enforces that only one local intent can exist for a given publication slot. If a timeout occurs while in CREATE\_IN\_FLIGHT, the worker cannot deterministically know the provider's state. It must update the local state to QUARANTINED. A highly conservative automated reconciliation script or a human operator must then inspect the provider's dashboard or logs. If the generation is verified as lost, the state is reverted to CREATE\_ELIGIBLE. If the generation succeeded but was disconnected, it is manually linked or discarded. This protocol strictly bounds duplicate cost risk without jeopardizing publication safety.
8.2 Configuration Fingerprinting
To prevent configuration drift—where a deployment changes the expected AI model or schema while a long-running job is still active—the CREATE\_ELIGIBLE transition must compute a cryptographic hash (e.g., SHA-256) of the complete prompt, model name, temperature, and JSON schema. This configuration\_fingerprint is persisted in the database. Upon resuming the job after a pause or server reboot, the worker recalculates the fingerprint against the current codebase. If the fingerprint mismatches, the active job is transitioned to QUARANTINED. Proceeding with a mismatched schema risks parsing failures, hallucinated data ingestion, and broken validation logic.
8.3 Identifier Taxonomy
Robust orchestration requires precise identifier management:
- Local Job ID: A UUIDv4 primary key representing the local orchestration workflow, decoupling internal tracking from provider-specific nomenclature.
- Provider Response ID: The resp\_abc123 identifier returned by the API. Nullable until the ACCEPTED state is reached.
- Current State Revision (Fencing Token): An integer starting at 1, incremented on every database update, acting as the mechanism for optimistic concurrency control.
- Lease Owner: A unique identifier generated by the specific PHP process or worker thread holding the lock.
- Lease Expiry: A UTC timestamp indicating when the lock naturally expires, allowing dead worker detection.
- Publication Artifact Hash: A cryptographic hash of the final JSON or HTML payload to prevent double-inserting identical content into the Content Management System (CMS).
9. Concurrency, Locking, and Time Authority
In standard PHP/LiteSpeed hosting environments, a script executing a background job may crash, hit the max\_execution\_time limit, or continue running detached in the background entirely invisible to the user due to functions like ignore\_user\_abort() or LiteSpeed's LSAPI\_AVOID\_FORK behavior1. These environmental realities make pure time-based locking highly dangerous.
9.1 The Vulnerability of Pure Time-Based Leases
Consider a scenario where two cron processes are active. Process A acquires a lock on a job with a 60-second TTL. During processing, Process A experiences a slow disk write or a severe CPU stall (e.g., garbage collection pause) and freezes. After 60 seconds, the lock naturally expires. Process B detects the expired lock, acquires it, reads the database state, and begins processing the same job. Meanwhile, Process A wakes up from its stall and blindly writes its stale data to the database, overwriting Process B's progress. This constitutes a classic split-brain lease failure3.
9.2 Mandatory Implementation of Fencing Tokens
To safely expire leases without allowing a slow, resurrected worker to corrupt data, the system must utilize Fencing Tokens via optimistic concurrency control3. The database, not the application code, enforces mutual exclusion. The protocol operates in three phases:
1. Acquisition: The worker attempts to claim an unowned or expired lease while incrementing the version token.
SQL
UPDATE jobs
SET lease\_owner \= 'worker-uuid',
lease\_expiry \= 'now \+ 60s',
version \= version \+ 1
WHERE id \= 123
AND (lease\_expiry \< 'now' OR lease\_owner IS NULL);
2. Retrieval: The worker reads the job row and stores the version locally in memory.
3. Commit: Upon completing the work phase, the worker attempts to transition the state, requiring the memory version to match the database version.
SQL
UPDATE jobs
SET state \= 'COMPLETED',
version \= version \+ 1
WHERE id \= 123
AND version \= \<memory\_version\>;
If Process A wakes up after 60 seconds and attempts its commit, the version will have already been incremented by Process B's acquisition. The UPDATE query will affect 0 rows. Process A detects this zero-row result, throws a FencingTokenException, and cleanly terminates without corrupting the state.
9.3 Resolving Specific Concurrency Scenarios
- Two cron processes starting simultaneously: Database row-level locks ensure only one process succeeds in the Acquisition UPDATE.
- Concurrent English and Spanish routes: Both routes map to the same edition\_date. Only one process creates the base candidate array. The workflow then forks into separate database rows for translation, protected by independent fencing tokens.
- Process dying while holding a lock: The lease\_expiry timestamp naturally passes in the database. The next cron invocation acquires the lock seamlessly without requiring manual intervention.
- Daily Brief and Revolution Watch operating concurrently: Different product targets utilize independent local job IDs and unique keys, preventing lock contention across distinct editorial products.
9.4 Time Authority
The relational database, stored strictly in Coordinated Universal Time (UTC), acts as the absolute authority for time. PHP application logic calculates time diffs based on the timestamp retrieved from the database, rather than relying on the web server's local clock. This architectural decision eliminates clock skew between PHP nodes, ignores daylight-saving time anomalies, and prevents the execution of stale retry logic following a server reboot33.
10. Exactly-Once Publication via Sagas and Outboxes
Attaining exactly-once publication effects over unreliable infrastructure requires decoupling the computation of the state from the projection or visibility of the state. The Challenge:
1. At-least-once cron execution guarantees mean a worker might process the same READY\_TO\_COMPOSE job twice.
2. Network retries mean the finalized edition payload might be submitted to the downstream CMS API twice.
3. Process crashes mean a worker might die immediately after writing a public file but before updating the local database status.
10.1 The Transactional Outbox Pattern
To solve the dual-write problem, the system utilizes the Transactional Outbox pattern7. When an edition transitions to the PUBLISHED state, the worker executes a single, atomic relational database transaction:
SQL START TRANSACTION; \-- 1\. Advance the state using fencing token validation UPDATE jobs SET state \= 'PUBLISHED', version \= version \+ 1 WHERE id \= 123 AND version \= 4;
\-- 2\. Insert the immutable edition content INSERT INTO editions (date, content, lang) VALUES ('2026-07-30', '{...}', 'en');
\-- 3\. Queue the event for external propagation INSERT INTO outbox (event\_type, payload) VALUES ('EditionPublished', '{"id": 123}'); COMMIT;
If the PHP process crashes mid-transaction, the database automatically rolls back. Neither the state change, the edition content, nor the outbox event is persisted. The next cron tick seamlessly resumes from the READY\_TO\_COMPOSE state. If the transaction commits, the effect is durable and atomic. A secondary, asynchronous Outbox Relay process polls the outbox table, reads the event, and makes idempotent calls to update public static files or RSS feeds, retrying indefinitely on network failure. Because the editions table employs a unique constraint on (date, lang), duplicate inserts are mechanically impossible, guaranteeing exactly-once logic at the storage layer34.
10.2 The Saga Pattern for Compensating Actions
For long-lived workflows, traditional ACID (Atomicity, Consistency, Isolation, Durability) transactions cannot hold locks across external APIs. Instead, the architecture utilizes the Saga pattern12. If a bilingual composition fails validation after the evidence has been successfully bound from the provider, the system does not roll back the entire process. It transitions to VALIDATION\_FAILED\_RETAINED. The valid evidence docket is preserved as a compensating checkpoint, avoiding the financial and temporal cost of re-purchasing the same evidence during the repair round.
11. Cancellation, Expiration, and Quarantine Protocols
The treatment of abandoned, expired, or cancelled remote work requires strict procedural boundaries.
11.1 Provider Completion vs. Publication Completion
A critical error in fragile architectures is equating a provider status of completed with successful workflow execution. The provider completion only indicates that the data is ready for retrieval. The data must be explicitly fetched via GET /responses/{id} and saved to local disk or database, transitioning the state to RETRIEVED\_NOT\_VALIDATED. If the system pauses before retrieval, the temporary background retention window (roughly 10 minutes) will expire, resulting in a 404 Not Found error and the permanent loss of the data6.
11.2 Cancellation Races
When a user or timeout protocol initiates a cancellation, the local system issues a POST /responses/{id}/cancel request. This request is best-effort38. A race condition exists where the provider completes the generation mere milliseconds before processing the cancellation. The architecture must handle this by inspecting the actual terminal status returned. If the provider indicates completed despite the cancellation attempt, the local system must proceed with the COMPLETED\_NOT\_RETRIEVED workflow, harvesting the data rather than discarding paid-for computation.
11.3 Ephemeral Deletion Safeguards
The system must never transmit a DELETE /responses/{id} request to the provider unless the local database has durably recorded the payload (RETRIEVED\_NOT\_VALIDATED) or an operator has issued an explicit manual kill command. Premature deletion irrevocably destroys the remote artifact.
12. Durable-Wakeup Comparison Matrix
To guarantee progress without depending on a user's open browser tab or active dashboard session, the system requires an independent, durable wakeup mechanism.
| Mechanism | Reliability | Implementation Complexity | Suitability for Small Host (PHP) | Verdict |
|---|---|---|---|---|
| System Cron (crontab) | High | Low | High | Primary Recommendation. Executing a CLI script (e.g., php bin/console workflow:tick) every 60 seconds provides a resilient, predictable heartbeat. |
| Hosting-Panel Cron | Moderate | Low | High | Acceptable fallback if bare-metal CLI access is restricted (e.g., cPanel/Plesk). |
| Systemd Timers | Very High | Moderate | Low (Requires Root) | Excellent precision, but frequently unavailable in managed or shared VPS environments. |
| Provider Webhooks | High | Low | High | Excellent for push-based acceleration. OpenAI supports Standard Webhooks41. Requires exposing a public endpoint and handling HMAC signature verification17. Must be paired with cron as a fallback for missed deliveries. |
| Lightweight Queue (Redis) | High | Moderate | Moderate | Overkill for the limited volume (e.g., 14-item daily workflows); introduces unnecessary failure domains to a simplified stack. |
| Operator Browser Wakeup | Low | Low | High | Acceptable only as an opportunistic trigger (e.g., viewing the admin dashboard triggers a background poll). Correctness must never depend on it. |
13. Non-Negotiable Invariants
To prove the correctness of the system mechanically, the software architecture must enforce the following non-negotiable invariants:
1. Budget Segregation Invariant: A polling operation must never increment the generation attempt counter.
2. Durable Custody Invariant: A transition to any publication state is prohibited until the provider payload is successfully committed to local persistent storage.
3. Ambiguity Quarantine Invariant: A transition out of CREATE\_IN\_FLIGHT that lacks a valid HTTP 200/202 and a response\_id must unconditionally transition the job to QUARANTINED. Blind retries are strictly forbidden.
4. Monotonic Fencing Invariant: Every state mutation written to the database must include the optimistic concurrency clause WHERE version \= current\_version. If affected rows equal 0, the worker must abort execution immediately.
5. Deletion Safety Invariant: A DELETE request to the provider API may only be dispatched if the job state is [Figure omitted from source export] RETRIEVED\_NOT\_VALIDATED or explicitly flagged for manual termination.
6. Model Continuity Invariant: Once a job reaches ACCEPTED, all subsequent retrievals and parsing operations must validate against the initially recorded configuration fingerprint.
14. Architectural Recommendations
14.1 Minimum Reliable Architecture (PHP/LiteSpeed)
For a modestly hosted intelligence publication operating without Kubernetes or dedicated orchestration teams, the following architecture is recommended:
1. Storage Layer: MySQL/MariaDB serves dual purposes: acting as the durable state machine and the distributed locking mechanism via InnoDB optimistic locking.
2. Trigger Mechanism: A single System Cron job running every 60 seconds invokes a headless PHP CLI script. This script sweeps the database for active jobs, acquires leases via fencing tokens, and advances the state machine.
3. Webhook Acceleration (Optional): An endpoint /api/webhooks/openai accepts push notifications. It employs a constant-time HMAC-SHA256 comparison43 to verify the webhook-signature. Valid webhooks immediately trigger the transition from IN\_PROGRESS to COMPLETED\_NOT\_RETRIEVED. The cron job acts as a continuous safety net for missed webhooks.
14.2 Advanced Architecture (Scale-Up Trigger)
Migration to a dedicated durable-workflow platform (such as Temporal or Azure Durable Functions20) is justified only when:
Until these thresholds are breached, introducing an enterprise workflow engine to a PHP/LiteSpeed stack introduces severe operational overhead (e.g., managing Go/Java/TypeScript worker fleets, gRPC networking, and Cassandra/PostgreSQL persistence).
- The volume of parallel editions exceeds 1,000 discrete workflows per day.
- The organizational capability scales to include full-time infrastructure engineers.
- The workflow evolves to encompass cross-service sagas requiring distributed transactions across multiple independent microservices written in different languages.
15. Failure-Injection Analysis (30 Scenarios)
The architecture's resilience is validated against 30 concrete failure scenarios, encompassing infrastructure, network, and application-level degradation.
| ID | Scenario | Detection | Containment | Safe State Transition | Auto Recovery | Operator Action | Evidence |
|---|---|---|---|---|---|---|---|
| 1 | Cron never installed | Dashboards show NO\_JOB past deadline | Jobs remain idle; no partial state | None | None | Install cron | last\_run is null |
| 2 | Cron uses wrong PHP | CLI throws syntax error immediately | Fails before DB access | None | None | Update path | Cron stderr logs |
| 3 | Cron uses wrong docroot | Script not found exception | Fails before DB access | None | None | Update path | Cron stderr logs |
| 4 | Cron user lacks write permission | File logging fails | DB state unchanged | None | None | Chmod logs | Permission Denied error |
| 5 | Cron runs twice concurrently | Fencing token collision on lease | 2nd process gets 0 rows on UPDATE | 1st proceeds normally | 2nd aborts cleanly | None | 0 rows affected in DB |
| 6 | Cron stops for 6h, then resumes | Lease expired in DB | Next cron picks up stale lease | IN\_PROGRESS \-\> EXPIRED | Creates new attempt | None | EXPIRED status logged |
| 7 | Browser & cron fire simultaneously | Fencing token collision | Only one process increments version | Loser aborts | Winner proceeds | None | Lock exception thrown |
| 8 | Two language routes attempt same work | Edition lock collision | DB Unique Constraint Violation | One proceeds | 2nd waits for 1st output | None | Constraint violation |
| 9 | Provider create success, local timeout | Response ID missing | State stuck in CREATE\_IN\_FLIGHT | QUARANTINED | None (Ambiguous) | Check provider dashboard | Timeout trace |
| 10 | Response ID stored, state transition fails | Row state invalid | Fails next load | Re-read ID from JSON/Logs | Yes (Algorithmic) | None | Transaction rollback logs |
| 11 | Local state written, fsync fails | Database corruption detected | DB rolls back transaction | Reverts to prior state | Yes (Next tick) | None | MySQL error log |
| 12 | Provider remains queued unusually long | poll\_count climbs | Exceeds SLA threshold | QUARANTINED | None | Cancel/Retry manually | poll\_count \> 30 |
| 13 | Provider reports in\_progress forever | poll\_count climbs | Exceeds SLA threshold | QUARANTINED | None | Cancel/Retry manually | poll\_count \> 30 |
| 14 | Provider completed, retrieval fails | HTTP 500 on GET payload | Retry fetch next tick | Stays COMPLETED\_NOT\_RETRIEVED | Yes | None | 500 status code |
| 15 | Completed output retrieved twice | Fencing token blocks 2nd commit | Duplicate payload discarded | RETRIEVED\_NOT\_VALIDATED | Yes | None | Version mismatch error |
| 16 | Validation succeeds, edition save fails | DB Exception | Rollback to pre-save state | READY\_TO\_COMPOSE | Yes (Retries compose) | None | Rollback event |
| 17 | Edition save succeeds, status not updated | Handled by Tx Outbox | Enclosed in single DB transaction | SAVED\_NOT\_PUBLIC | N/A (Atomic success) | None | Outbox event queued |
| 18 | Public file exists, index update fails | Outbox consumer fails | Retry outbox event | PUBLISHED (Index pending) | Yes | None | Unprocessed outbox row |
| 19 | Cleanup runs before durable publication | Guard clause prevents execution | Cleanup aborted | Stays PUBLISHED | Yes | None | State invariant log |
| 20 | Cleanup fails after successful publish | HTTP 500 on DELETE | Retries next tick | Stays CLEANUP\_PENDING | Yes | None | 500 on DELETE request |
| 21 | Response expires before retrieval | API returns 404 | Payload lost | PROVIDER\_EXPIRED... | Yes (New ID needed) | None | 404 response logged |
| 22 | Provider returns 404 for active ID | ID invalid remotely | Tainted state | PROVIDER\_EXPIRED... | Yes (New ID needed) | None | 404 response logged |
| 23 | Retry timestamp in future post-completion | Webhook pushes update | Preempts timestamp | COMPLETED\_NOT\_RETRIEVED | Yes | None | Webhook log entry |
| 24 | Attempt budget exhausted, work active | Max attempts hit | Stops polling | QUARANTINED | None | Manual fetch | Attempt max limit log |
| 25 | Config changes while work active | Fingerprint mismatch | Aborts processing | QUARANTINED | None | Manual update | Hash mismatch error |
| 26 | Deployment occurs between stages | Worker graceful shutdown | Next cron loads new code | Progresses normally | Yes | None | PID change logged |
| 27 | Server clock moves backward/forward | Diff uses relative DB time | lease\_expiry may false-expire | Fencing token protects data | Yes | Check NTP | NTP drift logs |
| 28 | Lock file remains after process death | DB lease expiry supersedes | Next worker ignores lock file | Overwrites lease | Yes | None | DB lease update |
| 29 | Slow disk operation outlives lease | Fencing token blocks commit | Transaction rolls back | State unchanged | Next worker wins | None | Version constraint error |
| 30 | Daily Brief & Rev Watch compete | Different target IDs | Independent locks | Progresses normally | Yes | None | Dual progress observed |
| 31 | Malicious repeated POST attempts | Idempotency Key / DB Unique | Rejected at network edge | NO\_JOB | N/A | None | HTTP 409 Conflict |
16. SLI, SLO, and Error-Budget Recommendations
For a small operations team, monitoring telemetry must be high-signal and low-noise.
- SLI 1: Time to Dispatch. Measured from scheduled target intent (NO\_JOB) to network transmission (CREATE\_IN\_FLIGHT).
- SLO: 99% within 2 minutes.
- SLI 2: Unretrieved Dwell Time. Maximum queued time between the provider indicating completion (COMPLETED\_NOT\_RETRIEVED) and local persistence (RETRIEVED\_NOT\_VALIDATED).
- SLO: 99% within 3 minutes (Strictly protects against the 10-minute provider expiration window6).
- SLI 3: Overdue Poll Interval. Time elapsed between the expected lease expiry and the actual next worker acquisition.
- SLO: 95% within 90 seconds.
- SLI 4: Duplicate Publication Rate. Number of identical editions rendered publicly to the end user.
- SLO: 0%. (This is a strict mathematical constraint enforced by unique database keys).
- SLI 5: Stranded Job Rate. Jobs residing in a non-terminal state older than 2 hours.
- SLO: \< 1 per month.
Error Budget Utilization: Assuming one Daily Brief and one Revolution Watch per day (approx. 730 executions annually), a 99% SLO permits roughly 7.3 delayed deliveries per year. When the error budget is exhausted, automated updates to prompt structures or infrastructure changes must be frozen until reliability margins are restored.
17. Recovery and Reconciliation Algorithm
The following pseudocode defines the reconciliation loop executed by the system cron daemon to safely evaluate active, stranded, and recovering jobs. Algorithm: ReconcileWorkflow Input: current\_utc\_time Execution Frequency: Every 60 seconds
1. SELECT jobs WHERE state NOT IN (PUBLISHED, DELETED, QUARANTINED)
AND lease\_expiry \< current\_utc\_time
2. FOR EACH job IN jobs:
3. // 1\. Acquire Lease with Fencing Token (Optimistic Concurrency)
4. rows\_affected \= EXECUTE(
UPDATE jobs
SET lease\_owner \= $worker\_id, lease\_expiry \= current\_utc\_time \+ 60s, version \= version \+ 1
WHERE id \= job.id AND version \= job.version
)
5. IF rows\_affected \== 0:
6. CONTINUE // Another worker successfully won the lease
7. // 2\. Evaluate State
8. SWITCH job.state:
9. CASE CREATE\_ELIGIBLE:
10. FencedUpdate(job, state=CREATE\_IN\_FLIGHT)
11. response \= HttpPost(OpenAI)
12. IF response.is\_timeout():
13. FencedUpdate(job, state=QUARANTINED) // Ambiguous timeout detected
14. ELSE IF response.ok():
15. FencedUpdate(job, state=ACCEPTED, response\_id=response.id)
16. CASE ACCEPTED, QUEUED, IN\_PROGRESS:
17. IF job.poll\_count \> 30:
18. FencedUpdate(job, state=QUARANTINED)
19. CONTINUE
20. status\_response \= HttpGet(OpenAI, job.response\_id)
21. job.poll\_count++
22. IF status\_response \== 'completed':
23. FencedUpdate(job, state=COMPLETED\_NOT\_RETRIEVED)
24. ELSE IF status\_response \== 404 OR expired:
25. FencedUpdate(job, state=PROVIDER\_EXPIRED\_OR\_MISSING)
26. CASE COMPLETED\_NOT\_RETRIEVED:
27. payload \= HttpGetPayload(OpenAI, job.response\_id)
28. SaveToDiskOrDatabase(payload)
29. FencedUpdate(job, state=RETRIEVED\_NOT\_VALIDATED)
30. CASE RETRIEVED\_NOT\_VALIDATED:
31. IF ValidateSchemaAndContent(job.payload):
32. FencedUpdate(job, state=READY\_TO\_COMPOSE)
33. ELSE:
34. FencedUpdate(job, state=VALIDATION\_FAILED\_RETAINED)
35. CASE READY\_TO\_COMPOSE:
36. edition \= ComposeBilingual(job.payload)
37. BEGIN TRANSACTION
38. FencedUpdate(job, state=PUBLISHED)
39. InsertEdition(edition)
40. InsertOutbox('PublishEvent', edition.id)
41. COMMIT TRANSACTION
Note: FencedUpdate is a critical security wrapper that applies the WHERE version \= expected\_version invariant to every database command. If the underlying database engine reports zero rows affected, execution halts immediately.
18. Deployment-Safe Migration and Rollback Strategies
Migrating from the legacy, fragile polling design (where a single shared counter tracked progress and public status checks refreshed displays without advancing work) requires a zero-downtime cutover sequence. Migration Sequence:
1. Phase 1: Schema Extension. Deploy the new database columns: version (defaulting to 1), lease\_owner, lease\_expiry, poll\_count, and generation\_attempts. Do not alter the application logic yet.
2. Phase 2: Shadow Tracking. Deploy the new state definitions. The legacy polling system continues to publish but emits asynchronous events mapping its actions to the new canonical states. Verify state mapping accuracy via logs.
3. Phase 3: Write Delegation. Switch the publication write-path to the new Transactional Outbox. The legacy system polls, but upon completion, hands the payload to the new READY\_TO\_COMPOSE state engine.
4. Phase 4: Full Cutover. Disable the legacy browser-based/public-polling trigger entirely. Enable the system cron to execute the ReconcileWorkflow algorithm.
5. Phase 5: Cleanup. Safely drop the legacy columns (e.g., the dangerous shared attempt counter).
Rollback Strategy: If Phase 4 introduces unexpected latency or strands jobs:
1. Immediate Abort: Run a CLI command to disable the system cron trigger, pausing all automated processing.
2. State Translation: Run a script that maps CREATE\_IN\_FLIGHT and ACCEPTED jobs back to the legacy system's pending queue structure.
3. Frontend Re-enable: Re-enable the legacy browser-polling triggers.
4. Because the response\_id is preserved identically in both systems, the legacy system can seamlessly pick up jobs that the new orchestration engine started but failed to finish.
19. Production-Readiness Checklist
- \[ \] Infrastructure Integrity: System cron is installed, running as the correct user, and logging standard output/error to a rotating file.
- \[ \] Time Synchronization: Network Time Protocol (NTP) is actively synchronized on the server; the database engine enforces UTC for all timestamp storage.
- \[ \] Database Constraints: Composite unique keys (date, channel, language) are active on the target editions table.
- \[ \] Process Protection: PHP max\_execution\_time is explicitly configured to safely exceed the cron lock lease (e.g., script max 55s, lease 60s) to prevent zombie processes1.
- \[ \] Security Constraints: OpenAI API keys are isolated via environment variables, strictly excluded from source control.
- \[ \] Webhook Validation: (If utilized) Standard Webhooks signature verification is implemented using a constant-time comparison library17.
- \[ \] Alerting Pathways: Monitoring alerts are configured to trigger immediately for any job entering the QUARANTINED or PROVIDER\_EXPIRED\_OR\_MISSING state.
20. Acceptance Test Plan (50 Tests)
A rigorous suite of automated integration and unit tests is required to validate the orchestration engine prior to production deployment. Core State Transitions (1-10)
1. Intent creation generates a valid UUID and sets initial state to NO\_JOB.
2. Transition to CREATE\_ELIGIBLE successfully claims the unique date lock.
3. Dispatched API call sets state to CREATE\_IN\_FLIGHT strictly before network I/O begins.
4. HTTP 200 saves the response\_id and advances to ACCEPTED.
5. Background poll updates poll\_count but leaves generation\_attempts mathematically unchanged.
6. API status completed transitions to COMPLETED\_NOT\_RETRIEVED.
7. Payload retrieval saves JSON to disk/DB and transitions to RETRIEVED\_NOT\_VALIDATED.
8. Validation failure correctly transitions to VALIDATION\_FAILED\_RETAINED.
9. Validation success correctly transitions to READY\_TO\_COMPOSE.
10. Final save transitions to PUBLISHED and generates a verified outbox event.
Idempotency & Concurrency (11-20) 11\. Two simultaneous requests to start the same edition yield exactly one CREATE\_ELIGIBLE job; the second returns an HTTP 409 Conflict. 12\. Fencing token check: Modifying a job with a stale memory version throws a FencingTokenException. 13\. UPDATE statement affecting 0 rows aborts the worker process cleanly. 14\. Lease acquisition logic strictly ignores jobs where lease\_expiry remains in the future. 15\. Lease acquisition claims jobs successfully where lease\_expiry is in the past. 16\. Process death mid-retrieval allows the next worker to retry after lease expiration without data corruption. 17\. Dual-language dispatch (English/Spanish) on the same dataset forks correctly post-validation without lock contention. 18\. Outbox processor strictly deduplicates identical publish events. 19\. Webhook delivery of response.completed gracefully handles out-of-order delivery (if job is already PUBLISHED, webhook 200s and exits harmlessly). 20\. Webhook replay attack fails explicitly due to the timestamp tolerance window (± 5 mins). Failure & Recovery (21-40) 21\. HTTP timeout during CREATE\_IN\_FLIGHT transitions job to QUARANTINED. 22\. 429 Too Many Requests triggers exponential backoff delay based on x-ratelimit-reset headers25. 23\. 500 Internal Server Error increments poll count but does not fail the job entirely. 24\. poll\_count exceeding 30 transitions the job to QUARANTINED. 25\. generation\_attempts exceeding 3 halts further creation attempts. 26\. HTTP 404 from the provider transitions to PROVIDER\_EXPIRED\_OR\_MISSING. 27\. Database disconnect during PUBLISHED transaction rolls back all state atomically. 28\. Provider payload schema mismatch safely parks in VALIDATION\_FAILED\_RETAINED. 29\. Cron overlapping triggers do not execute the identical HTTP GET request. 30\. Fingerprint mismatch between CREATE\_ELIGIBLE config and runtime config quarantines the job. 31\. Simulated 10-minute expiry on the provider side is caught by PROVIDER\_EXPIRED logic. 32\. Manual transition out of QUARANTINED correctly resets poll\_count to 0\. 33\. Suspending a job (MANUALLY\_SUSPENDED) prevents any subsequent lease acquisition. 34\. Outbox relay network failure leaves the event unprocessed; the next tick succeeds. 35\. Attempting to DELETE /responses/{id} before RETRIEVED\_NOT\_VALIDATED throws an internal invariant error. 36\. JSON parse error on the provider payload triggers a validation failure. 37\. Missing API key throws a configuration exception prior to lock acquisition. 38\. Disk full error during payload save triggers a graceful transaction rollback. 39\. Network unreachable during CLEANUP\_PENDING retries indefinitely without affecting publication visibility. 40\. Deleting an already-deleted remote response (HTTP 404 on DELETE) safely resolves to DELETED. Business Logic & SLA Constraints (41-50) 41\. Revolution Watch and Daily Brief workflows execute concurrently without lock contention. 42\. Historical backfill jobs yield scheduling priority to current-day active editions. 43\. Rate-limit wait times correctly respect x-ratelimit-reset timestamps. 44\. Payload validation strictness correctly rejects hallucinated URL structures. 45\. Bilingual composer enforces distinct output fields for English and Spanish formats. 46\. Source scout outputs exactly map to the required 14 candidate constraints. 47\. Evidence binder strictly rejects unauthorized web-search parameters in its configuration. 48\. System clock skew simulation proves relative DB-time protects lease integrity33. 49\. LSAPI\_AVOID\_FORK simulation confirms a detached worker does not hold infinite locks15. 50\. End-to-end load simulation processes 100 parallel jobs safely without dropping connections.
21. Incident-Response Runbook
When an SLO is breached (e.g., a job is stranded or duplicate publication is suspected), operators follow this temporal progression:
- T \+ 2 Hours (Triage & Contain):
- Check the administrative Dashboard for QUARANTINED states.
- If the job is stuck in CREATE\_IN\_FLIGHT: The network dropped. Verify the OpenAI dashboard for billing activity. If the job was generated remotely, manually copy the JSON payload to the local DB and advance the state to RETRIEVED\_NOT\_VALIDATED. If no remote activity exists, revert to CREATE\_ELIGIBLE.
- If the job is stuck in QUEUED: Check the OpenAI API status page. Do not cancel the job. Increase the poll budget manually via the database: UPDATE jobs SET poll\_count \= 0 WHERE id \= X.
- T \+ 1 Day (Investigation):
- Review LiteSpeed and PHP-FPM error logs for max\_execution\_time terminations or out-of-memory kills1.
- Ensure the cron daemon is executing exactly every 60 seconds without fail.
- Query the outbox table for blocked publication events preventing the final transition to the PUBLISHED state.
- T \+ 1 Week (Root Cause Analysis):
- Identify if the Ambiguous Timeout pattern is increasing in frequency. If so, investigate migrating to a provider endpoint with explicit Idempotency-Key headers for creation28, or implement an automated reconciliation script leveraging the provider's list endpoint to search for orphaned executions.
- T \+ 1 Month (Remediation):
- Tune the exponential backoff parameters. If 429 errors are persistent, implement a global Redis token bucket to throttle outbound network requests proactively across all workers before the provider enforces limits.
22. Decision Register
| ID | Decision / Finding | Category | Rationale |
|---|---|---|---|
| D1 | Separate Polling/Generation budgets | Recommendation | Prevents abandoning accepted, paid-for work due to slow remote queues22. |
| D2 | Fencing Tokens over TTL Leases | Design Inference | PHP execution environments can detach or stall; optimistic concurrency is mandatory to prevent data corruption3. |
| D3 | Zero Data Retention vs Background | Research Finding | ZDR (store: false) disables 30-day retention but background responses are still kept for \~10 minutes to allow polling6. |
| D4 | Idempotency Headers | Research Finding | Standard Responses API lacks documentation for strict Create idempotency keys (unlike Ads/Commerce endpoints)28. |
| D5 | Handle Ambiguous Timeout via Quarantine | Recommendation | Cannot safely retry a dropped network connection without risking dual generation and double billing. Human or script review required5. |
| D6 | Transactional Outbox for Publication | Design Inference | Dual-writes to a database and an external CMS will eventually fail; atomic local commits resolve this7. |
| D7 | Use Cron as Primary Wakeup | Recommendation | Simplest, most reliable trigger for a PHP/LiteSpeed shared environment without Kubernetes. |
| D8 | Provider completed \!= Published | Non-negotiable | Data must be fetched and persisted locally before it is considered secure and actionable. |
23. Source Register
- \[cite: 6\] OpenAI API Documentation: Responses API Background Mode. Describes background: true and 10-minute temporary storage parameters.
- \[cite: 6, 11\] OpenAI API Reference: Responses endpoints and status fields detailing exact strings (queued, in\_progress, completed, incomplete, failed).
- \[cite: 41, 42\] Webhooks Integration for OpenAI: Documents the webhook payload structure and asynchronous delivery paradigms.
- \[cite: 28, 29, 30, 46\] Idempotency-Key specifications: Present in OpenAI Commerce, Ads, and Workspace Trigger documentation, demonstrating varied support across endpoints.
- \[cite: 7, 8\] Transactional Outbox Pattern: AWS Prescriptive Guidance and Microservices.io on distributed dual-write resolution and eventual consistency.
- \[cite: 5\] Idempotency Patterns: "Building Retry-Safe Distributed Systems" detailing exactly-once fallacies and network realities.
- \[cite: 34, 35\] Transactional Outbox implementations: Ensuring atomic database writes and background worker isolation.
- \[cite: 3, 4, 47\] Distributed Locking and Fencing Tokens: Martin Kleppmann's "How to do distributed locking" detailing the necessity of monotonic tokens to prevent lease expiration races.
- \[cite: 31, 32\] Distributed consensus theory and lease failures.
- \[cite: 17, 18, 43\] Standard Webhooks Specification: Cryptographic signature verification, constant-time comparison, and replay window tolerance (±5 mins).
- \[cite: 12, 13, 14\] Sagas: Hector Garcia-Molina and Kenneth Salem (1987). Core theory for breaking long-lived transactions into compensated local steps.
- \[cite: 36, 37\] Saga implementations in microservices architectures.
- \[cite: 19, 20\] Workflow state machines and durable execution paradigms.
- \[cite: 20, 44\] Durable Execution: "Distributed Speculative Execution for Resilient Cloud Applications" (Li et al., 2024/2026), discussing state machine abstraction and architectural overhead.
- \[cite: 10, 23, 48\] OpenAI API Rate Limits: HTTP 429 handling and rate limit error structures.
- \[cite: 22, 23, 24\] OpenAI API Rate Limits: Backoff and jitter patterns for production environments.
- \[cite: 15, 45, 49\] LiteSpeed & PHP Configuration: FPM signal handling, LSAPI\_AVOID\_FORK, and detached worker execution constraints.
- \[cite: 21\] Error handling in distributed transactions and compensating logic.
- \[cite: 6, 9\] OpenAI Zero Data Retention (ZDR): Explains that store: false disables long-term training/abuse retention but retains background polling data for 10 minutes.
- \[cite: 20, 33\] Time synchronization, clock skew, and distributed execution architectures.
- \[cite: 25, 26, 27, 50\] Rate Limits: x-ratelimit-reset headers, exponential backoff, and jitter patterns for multi-agent workloads.
- \[cite: 38, 39, 40\] OpenAI API Cancel Response: POST /responses/{response\_id}/cancel behaviors, limitations, and best-effort termination semantics.
- \[cite: 1, 2\] PHP Configuration: max\_execution\_time, request\_terminate\_timeout, and ignore\_user\_abort detached process behaviors.
- \[cite: 16\] MySQL isolation levels (READ COMMITTED vs REPEATABLE READ) affecting transaction visibility.
24. Recommended Architecture Decision
Minimum Safe Design: Implement the relational 18-state machine in MySQL/MariaDB utilizing strict optimistic concurrency (Fencing Tokens) for all row updates. Drive the state machine entirely via a 60-second system cron invocation, insulating the architecture from browser tab dependency. Strict isolation must be maintained between the network initiation budget (generation\_attempts) and the status checking budget (poll\_count). The system must utilize the Transactional Outbox pattern to separate local database commits from external publication side-effects, guaranteeing exactly-once publication. Scale-Up Trigger: Migration to a dedicated durable execution framework (e.g., Temporal, Azure Durable Functions) is justified only when the system exceeds 1,000 parallel workflows per day or requires distributed sagas spanning multiple distinct microservices outside the core LAMP stack. Highest-Priority Failure Test: The Ambiguous Timeout (Scenario 9\). Operators must forcefully terminate the network connection during the CREATE\_ELIGIBLE to CREATE\_IN\_FLIGHT HTTP POST transition to guarantee the system parks the job in QUARANTINED rather than blindly retrying, incurring duplicate financial costs, and generating duplicate background artifacts.
Works cited
1. The php-fpm Tuning Cheat Sheet: 5 Settings That Decide Your p99 \- DEV Community, https://dev.to/gabrielanhaia/the-php-fpm-tuning-cheat-sheet-5-settings-that-decide-your-p99-5gp0
2. PHP Without Timeout | LiteSpeed Web Server, https://docs.litespeedtech.com/lsws/cp/cpanel/long-run-script/
3. Distributed Locks and Leases \- Meridian Space, https://rustycloud.org/distributed\_systems\_track/module-05-coordination/lesson-01-distributed-locks-leases.html
4. How to do distributed locking \- Martin Kleppmann, https://martin.kleppmann.com/2016/02/08/how-to-do-distributed-locking.html
5. Idempotency Patterns: Building Retry-Safe Distributed Systems \- Dotnetjalps, https://dotnetjalps.com/idempotency-patterns-building-retry-safe-distributed-systems/
6. Background mode | OpenAI API, https://developers.openai.com/api/docs/guides/background
7. Transactional outbox pattern \- AWS Prescriptive Guidance, https://docs.aws.amazon.com/prescriptive-guidance/latest/cloud-design-patterns/transactional-outbox.html
8. Pattern: Transactional outbox \- Microservices.io, https://microservices.io/patterns/data/transactional-outbox.html
9. Data controls in the OpenAI platform, https://developers.openai.com/api/docs/guides/your-data
10. Error codes | OpenAI API, https://developers.openai.com/api/docs/guides/error-codes
11. Responses | OpenAI API Reference, https://developers.openai.com/api/reference/python/resources/responses
12. Paper Summary: Sagas \- Dominik Tornow \- Medium, https://dominik-tornow.medium.com/paper-summary-sagas-395ef2a9a575
13. sagas.pdf \- Cornell: Computer Science, https://www.cs.cornell.edu/andru/cs711/2002fa/reading/sagas.pdf
14. SAGAS \- cs.Princeton, https://www.cs.princeton.edu/techreports/1987/070.pdf
15. LSAPI Release Log \- LiteSpeed Technologies, https://www.litespeedtech.com/open-source/litespeed-sapi/lsapi-release-log
16. How to Use REPEATABLE READ Isolation Level in MySQL \- OneUptime, https://oneuptime.com/blog/post/2026-03-31-mysql-repeatable-read-isolation-level/view
17. What is a webhook signature? | Svix Resources, https://www.svix.com/resources/glossary/webhook-signature/
18. standard-webhooks/spec/standard-webhooks.md at main \- GitHub, https://github.com/standard-webhooks/standard-webhooks/blob/main/spec/standard-webhooks.md
19. arXiv:2308.16517v1 \[cs.DC\] 31 Aug 2023, https://arxiv.org/pdf/2308.16517
20. Distributed Speculative Execution for Resilient Cloud Applications \- arXiv, https://arxiv.org/pdf/2412.13314
21. Common Mistakes with Microservices and Distributed Transactions | by Jacob George, https://medium.com/@jacob.ptpm/common-mistakes-with-microservices-and-distributed-transactions-03b6b00bfc0c
22. OpenAI API rate limits: practical guide for 2026 \- CodeWords, https://www.codewords.ai/blog/openai-api-rate-limits
23. Master OpenAI API Rate Limit Challenges \- SupportGPT, https://supportgpt.app/blog/openai-api-rate-limit
24. What Are the API Limits When Building Scalable ChatGPT Apps? \- WildnetEdge, https://www.wildnetedge.com/blogs/chatgpt-api-limits
25. NinjaPear API Reference, https://nubela.co/docs
26. Mapping AI Agent Patterns to Integration Platforms: The 2026 Engineering Guide \- Truto, https://truto.one/blog/mapping-ai-agent-patterns-to-integration-platforms-2026-tutorial/
27. 9 AI Agents, One API Quota — The Rate Limiting Problem Nobody Talks About | IBlogger, https://www.tamirdresher.com/blog/2026/03/21/rate-limiting-multi-agent
28. Overview – Agentic Commerce | OpenAI Developers, https://developers.openai.com/commerce/specs/api/overview
29. Bulk API – Ads \- OpenAI Developers, https://developers.openai.com/ads/bulk-api
30. Trigger workspace agent runs \- OpenAI Developers, https://developers.openai.com/workspace-agents/trigger-runs
31. Distributed Locking — Sujeet Jaiswal \- Principal Software Engineer, https://sujeet.pro/articles/distributed-locking
32. How to do distributed locking — Martin Kleppmann's blog \- Computer Sciences User Pages, https://pages.cs.wisc.edu/\~remzi/Classes/739/Papers/leases-redis-problem.pdf
33. How to Handle Clock Drift Issues After Network Outage \- OneUptime, https://oneuptime.com/blog/post/2026-03-31-rook-handle-clock-drift-after-network-outage/view
34. Transactional Outbox: How to safely offload work into the background \- Dennis, https://dnnsthnnr.com/blog/transactional-outbox-how-to-safely-offload-tasks-into-the-background
35. Transactional Outbox with RabbitMQ (Part 1): Building Reliable Event Publishing in Microservices \- DEV Community, https://dev.to/sagarmaheshwary/transactional-outbox-with-rabbitmq-part-1-building-reliable-event-publishing-in-microservices-2of
36. The Saga pattern in distributed systems \- Anurag Dulapalli, https://anuragdulapalli.com/posts/saga-pattern/
37. Saga Pattern for Microservices Explained \- Conduktor, https://www.conduktor.io/glossary/saga-pattern-for-distributed-transactions
38. Cancel a response | OpenAI API Reference, https://developers.openai.com/api/reference/resources/responses/methods/cancel
39. Cancel a response | OpenAI API Reference, https://developers.openai.com/api/reference/ruby/resources/responses/methods/cancel
40. Unexpected Behavior in Background Responses API – Status Changes from "Cancelled" to "Completed" \- Microsoft Learn, https://learn.microsoft.com/en-us/answers/questions/2339607/unexpected-behavior-in-background-responses-api-st
41. OpenAI Webhooks: A Complete Guide for Customer Support Teams \- Kommunicate, https://www.kommunicate.io/blog/openai-webhooks/
42. OpenAI Webhooks Integration Example: Handle Deep Research & Batch Jobs, https://codehooks.io/docs/examples/webhooks/openai
43. Webhooks \- ComplyAdvantage, https://docs.mesh.complyadvantage.com/docs/webhooks
44. Durable Functions: Semantics for Stateful Serverless \- Konstantinos Kallas, https://angelhof.github.io/files/papers/durable-functions-2021-oopsla.pdf
45. "No request delivery notification has been received from LSAPI application, possible dead lock." · Issue \#186 · litespeedtech/openlitespeed \- GitHub, https://github.com/litespeedtech/openlitespeed/issues/186