Blog › ICP guides
GeneXus developer on retainer: For Each Update deferred commit lock hold, GeneXus Ev3 developer, GeneXus 17 developer on monthly retainer
October 9, 2026 · ~15 min read
A GeneXus developer was maintaining a manufacturing company’s order management system running GeneXus Ev3 (Evolution 3) with a SQL Server backend. The application had 120 concurrent users across 4 shifts. A batch Procedure named ProcessPendingOrders ran nightly at 11 PM to update order statuses from ‘Pending’ to ‘Processing’ after inventory confirmation. The Procedure used a For Each Orders Where Status = 'Pending' block with the Update verb to modify each order record — GeneXus generates a SQL Server UPDATE Orders SET ... WHERE OrderId = ... with an UPDLOCK hint for each record in the iteration. The Procedure had Commit on Exit = Yes (the GeneXus default for Procedures): all changes are accumulated in a single deferred transaction and committed in a single COMMIT TRANSACTION when the Procedure exits normally. With 500 pending orders, the batch run held 500 SQL Server UPDATE row-level locks for the entire 40-minute batch duration. Operators on the night shift opening order-entry forms received SQL Server lock-wait timeout errors (default 30 seconds) when attempting to access any order record that was in the ‘Pending’ batch. Lock-wait timeouts per batch run: 500 order locks held for 40 minutes → 0 per-iteration lock hold after adding an explicit Commit() call inside the For Each loop.
The root cause was GeneXus’s deferred commit model for Procedures. In GeneXus, a Procedure with Commit on Exit = Yes accumulates all database changes within the Procedure’s scope in a single DB transaction. GeneXus generates a BEGIN TRANSACTION at the start of the Procedure’s first database operation and a COMMIT TRANSACTION when the Procedure exits normally (or ROLLBACK TRANSACTION if an unhandled error occurs). For Each ... Update inside the Procedure iterates over records matching the Where clause and issues individual UPDATE SQL statements — each UPDATE acquires an exclusive row-level lock on the Orders record via the UPDLOCK hint in GeneXus’s SQL Server-generated code (or SELECT FOR UPDATE on PostgreSQL and Oracle). These locks are not released until the transaction commits. With 500 iterations accumulating 500 UPDATE locks over a 40-minute run, the Procedure holds a 500-row lock set for the full duration. GeneXus’s Commit() built-in procedure (available in GeneXus Ev3 and later) issues an explicit COMMIT TRANSACTION and starts a new transaction — releasing all locks acquired so far. Adding Commit() at the end of each For Each loop iteration changes the lock-hold pattern from one 40-minute 500-lock transaction to 500 per-iteration transactions, each releasing its lock immediately after the update.
The invisibility of the bug has two distinct layers. First, the developer who tested ProcessPendingOrders ran it against a 10-order test set in a development environment with no concurrent users. The batch completed in under 3 seconds; no lock-wait errors were observed. GeneXus’s generated SQL and GeneXus Studio’s test runner show no indication that locks are accumulating — GeneXus Studio does not surface a “current active locks” counter or a warning that a For Each Update loop under Commit on Exit = Yes will hold all acquired locks until Procedure exit. Second, the lock-wait errors received by night-shift operators were not visually connected to the batch Procedure in their GeneXus web application — they saw a generic “Error accessing database” message from the GeneXus web application’s error handler, which logged SQL Server error 1222 (“Lock request time out period exceeded”) but did not name ProcessPendingOrders as the lock holder. The DBA identified the holding transaction only by querying sys.dm_exec_sessions joined to sys.dm_tran_locks in SQL Server Management Studio and tracing the session back to the JDBC connection pool used by the GeneXus application server hosting ProcessPendingOrders. The gap between the operator-visible error (“Error accessing database”) and the root cause (“GeneXus batch Procedure holding 500 row-level UPDATE locks for 40 minutes”) is wide enough that the bug can persist through multiple incident reports without diagnosis, each night-shift incident closed as “intermittent database error, resolved by retry.”
GeneXus: Artech’s knowledge base-driven development platform from Montevideo
GeneXus was founded by Nicolás Jodal and Breogán Gonda at Artech (later GeneXus S.A.) in Montevideo, Uruguay in 1988. The fundamental GeneXus concept is the Knowledge Base — a repository of “Knowledge” encoding business rules, data structures, user interface patterns, and validation logic, from which GeneXus generates application code for the target platform. GeneXus was designed so that the developer describes what the application should do — in terms of Transactions (the primary data-entry form), Procedures (explicit code components), Web Panels (event-driven web UI), and Data Providers (read-only data transformation objects) — and GeneXus determines how to implement it, generating Java, .NET, or RPG code and database DDL from the Knowledge Base. This approach made GeneXus applications automatically forward-compatible: when GeneXus added support for a new database backend or a new frontend framework, existing Knowledge Bases could be regenerated for the new target without rewriting application logic. A GeneXus developer who adds an attribute to an Orders Transaction does not manually write the ALTER TABLE statement; GeneXus analyzes the Knowledge Base, determines the DDL delta from the prior model, and generates the migration script alongside the new application code.
GeneXus’s evolution spans four decades of platform generations. GeneXus originally generated COBOL for mainframes and RPG for AS/400 — the platform was born in the IBM midrange computing era that dominated Latin American enterprise IT in the late 1980s and 1990s. As client-server computing emerged in the 1990s, GeneXus added generators for C and Visual Basic. The web era brought Java and .NET generators. GeneXus Ev1 (Evolution 1) in 2008 introduced a redesigned web generation model using the GeneXus Web Framework, moving away from classic HTML-form generation toward a richer AJAX-capable web UI. GeneXus Ev2 (2010) and Ev3 (2012) expanded web and mobile generation. GeneXus 15 (2017) added Smart Device generators for native iOS and Android and introduced the Deployment Unit concept for packaging GeneXus applications for cloud infrastructure. GeneXus 16 (2019) and GeneXus 17 (2021) added low-code features, REST API publishing via GeneXus Services and GeneXus API Gateway, and cloud deployment templates for AWS, Azure, and Google Cloud. GeneXus 18 (2023) added AI and LLM integration patterns for embedding machine learning inference calls directly into GeneXus Procedures and Web Panels. Throughout this evolution, the core GeneXus transaction model and commitment control architecture remained consistent — a GeneXus application built in Ev1 has essentially the same transaction semantics as one built in GeneXus 17, which is why the For Each Update deferred commit lock-hold bug is equally present across all GeneXus versions from Ev1 through 18.
GeneXus gained dominant market share in Latin America — Uruguay, Argentina, Brazil, Mexico, Chile, and Colombia — and significant adoption in Japan, where Artech formed a strategic partnership with Japanese systems integrators in the 1990s that resulted in GeneXus becoming a mainstream enterprise development platform for Japanese government agencies and manufacturing companies. Many government agencies, financial institutions, and manufacturing companies across Latin America and Japan run core business systems on GeneXus applications that were developed in the 1990s and 2000s. Retainer developers maintain these systems as the original development teams have turned over: the developers who built the original Knowledge Base in GeneXus Ev1 may have left the organization, and the current IT team inherits a Knowledge Base they did not design. GeneXus Knowledge Bases are version-controlled using the .xpz export format, and the Knowledge Base is the primary artifact for maintenance — not the generated Java or .NET code, which is regenerated from the Knowledge Base and should never be edited directly. A GeneXus retainer developer who can navigate the Knowledge Base, identify the relevant Transaction, Procedure, or Web Panel, add a Commit() call after the appropriate For Each Update iteration, regenerate only the affected Procedure object, and deploy the new generated code without triggering a full Knowledge Base regeneration is the profile most in demand for Latin American and Japanese enterprise GeneXus maintenance retainers.
The GeneXus transaction model establishes a precise distinction between object types and their commitment control behavior. Transaction objects are the primary data-entry form in GeneXus; they have an implicit Begin/Commit/Rollback lifecycle tied to the form’s Save/Cancel/Error events — when the user clicks Save, GeneXus issues a COMMIT; when the user clicks Cancel, GeneXus issues a ROLLBACK. Transaction objects hold their DB locks only for the duration of the Save event handler, which is typically sub-second. Procedures and Data Providers are explicit code components with a Commit on Exit property that controls the transaction boundary: when set to Yes (the default), the entire Procedure execution is wrapped in a single DB transaction. Web Panels fire client-side events within the transaction scope of the Web Panel session. Understanding which GeneXus object type is executing and what its Commit on Exit configuration is determines the lock-hold behavior. GeneXus’s generated SQL for SQL Server uses UPDLOCK hints for For Each Update and SELECT FOR UPDATE for PostgreSQL and Oracle; the lock-hold pattern is identical across all supported DBMS backends, though the specific SQL syntax and lock visibility in system views differs. The retainer developer must know which DBMS is behind the GeneXus application server to use the correct DMV queries for lock diagnosis.
GeneXus Procedure commit model, For Each Update, and SQL Server lock hold
GeneXus Procedure Commit on Exit property behavior is the axis around which all GeneXus batch lock-hold bugs rotate. When set to Yes (the default), GeneXus wraps the entire Procedure execution in a single DB transaction: the first database operation triggers BEGIN TRANSACTION; normal Procedure exit triggers COMMIT TRANSACTION; error exit (unhandled exception) triggers ROLLBACK TRANSACTION. For Each ... Update within the Procedure iterates over records matching the Where clause and issues an UPDATE for each matched row, accumulating both the change and the row-level lock for each record in the active transaction. For a 500-row iteration over the Orders table, the transaction holds 500 individual row-level UPDATE locks — one per row — from the moment each UPDATE executes until the COMMIT TRANSACTION fires when the Procedure exits, which in the ProcessPendingOrders case is 40 minutes later. SQL Server’s default lock escalation threshold is 5,000 locks on a single object: when a single transaction acquires more than 5,000 row-level locks on the same table, SQL Server automatically escalates to a table-level lock, replacing the 5,000 individual row locks with a single TABLE lock that blocks all access to the Orders table — not just the rows being processed. For a manufacturing company running 500 pending orders, the risk of table-level lock escalation is not immediate, but a month-end batch run or a catch-up run after a system outage could push the pending order count above 5,000, changing the impact from “500 orders blocked for order-entry users” to “entire Orders table blocked for all users for the full batch duration.” The Commit() fix eliminates both the per-row accumulation and the escalation risk by releasing locks per iteration.
GeneXus’s Commit() built-in procedure is the correct fix for the deferred commit lock-hold pattern. Commit() is callable from any GeneXus Procedure or Web Panel event as a statement — Commit() on its own line in the Procedure’s Rules or Source section. When called, Commit() issues a COMMIT TRANSACTION to the underlying DBMS and starts a new implicit transaction for subsequent operations. Calling Commit() inside a For Each Update loop after each iteration’s Update commits that iteration’s change and releases its lock before the next iteration begins. The lock-hold window per order shrinks from the full 40-minute batch duration to the time of a single iteration — typically milliseconds on a SQL Server with a local network GeneXus application server. The corrected GeneXus Procedure source pattern is: For Each Orders Where Status = 'Pending' / Orders.Status = 'Processing' / Commit() / EndFor. The explicit Commit() call overrides the Procedure’s Commit on Exit = Yes behavior for per-iteration commits while the Commit on Exit mechanism still issues a final COMMIT on Procedure exit for any trailing operations after the loop. An important caveat: adding Commit() inside a For Each Update loop means that if the Procedure encounters an error on iteration 300, the first 299 orders have already been committed and cannot be rolled back. For the ProcessPendingOrders use case — updating statuses after inventory confirmation — this is acceptable; for Procedures where atomicity across all iterations is a business requirement, an alternative architecture (chunked batches with per-chunk Commit, or a queue-based design with per-message acknowledgment) is needed.
Diagnosing GeneXus lock hold with SQL Server requires querying the Dynamic Management Views (DMVs) that expose active sessions and their lock state. The query that identifies sessions holding row-level locks on the Orders table is: SELECT s.session_id, s.login_name, t.resource_type, t.request_mode, t.request_status, t.resource_description FROM sys.dm_tran_locks t JOIN sys.dm_exec_sessions s ON t.request_session_id = s.session_id WHERE t.resource_type = 'RID' AND DB_NAME(t.resource_database_id) = 'OrdersDB' AND t.resource_associated_entity_id = OBJECT_ID('Orders'). This query returns one row per locked row (RID = Row ID lock) on the Orders table in the OrdersDB database, with the session ID and login name of the lock holder. GeneXus applications connect to SQL Server via JDBC (Java generator) or ADO.NET (.NET generator) connection pools; the login_name in the DMV result is typically the application pool service account (e.g., DOMAIN\gxappservice), which by itself does not identify which GeneXus Procedure is running. To identify the holding Procedure, use sys.dm_exec_sql_text(s.most_recent_sql_handle) — this function returns the most recent SQL text executed by the session, which will show the GeneXus-generated UPDATE Orders SET StatusId = ? WHERE OrderId = ? /* UPDLOCK */ statement with the Orders table name and the UPDLOCK hint that GeneXus injects for For Each Update on SQL Server. Cross-reference the table name in the generated SQL against the GeneXus Knowledge Base to identify which GeneXus Procedure contains a For Each Orders loop — in most production Knowledge Bases, only one or two Procedures iterate over the full Orders table by status. GeneXus trace logging (Trace=Yes in the GeneXus environment configuration) can confirm by writing a line for each Procedure invocation with start/end timestamps and SQL statement counts, allowing the retainer developer to correlate the trace log entry for ProcessPendingOrders with the DMV session holding the 500 row locks.
Typical GeneXus developer retainer work and what it looks like in a work log
For Each Update deferred commit lock hold in batch Procedure is the canonical GeneXus invisible production lock bug, and it appears in the work logs of nearly every GeneXus retainer engagement for manufacturing, financial, or government clients running batch Procedures against large tables. The pattern is consistent: Procedure uses For Each SomeTable Where SomeCondition with Update verb; Commit on Exit = Yes; development testing used a small data set with no concurrent users; production runs against hundreds or thousands of rows; night operators or daytime users on a different shift receive lock-wait timeout errors on the locked table; the incident is closed as “intermittent database error, retried successfully” for weeks before the retainer developer runs the DMV query. The work log entry that makes this diagnosable and auditable: “OrderMgmtKB (GeneXus Ev3, SQL Server 2019); Procedure ProcessPendingOrders; Commit on Exit = Yes; For Each Orders Where Status = ‘Pending’ / Update; production order count at 11 PM batch time: 500; batch duration: 40 minutes; SQL Server UPDATE row-level locks held at peak: 500 RIDs on Orders table; identified via sys.dm_tran_locks joined to sys.dm_exec_sessions — session login_name DOMAIN\gxappservice; most_recent_sql_handle decoded via sys.dm_exec_sql_text shows UPDATE Orders SET StatusId = 2 WHERE OrderId = ? with UPDLOCK hint; 8–12 lock-wait timeout errors (SQL Server error 1222) reported per batch run by night-shift operators on order-entry Web Panels; fix: explicit Commit() call inserted inside For Each loop after Orders.Status = ‘Processing’ assignment; lock hold per iteration after fix: released immediately after each Commit(); lock-wait timeout errors after fix: 0; 4h.”
GeneXus Knowledge Base maintenance — adding a new attribute to a Transaction is the routine day-to-day GeneXus retainer task that requires careful scoping to avoid unintended regeneration of unrelated components. The workflow: the client requests a new ExpectedShipDate date attribute on the Orders Transaction; the retainer developer opens the Knowledge Base, navigates to the Orders Transaction, adds the new attribute with its domain (Date), sets its Not Null constraint and default value rules, and saves the Transaction. GeneXus then marks all generated objects that depend on the Orders Transaction as “Outdated” — these include the Orders Web Panel, the Orders Report, any Procedure that navigates the Orders table via For Each Orders, and the database reorganization script that will add the ExpectedShipDate column to the Orders table in SQL Server. The retainer developer reviews the impact list in GeneXus Studio, verifying that the regeneration scope covers only the Orders-related objects and not unrelated Transactions or Web Panels that happen to share a common domain. The developer regenerates the affected objects, runs the database reorganization (GeneXus generates the ALTER TABLE script and applies it via the DB Reorganization wizard), deploys the new generated code to the GeneXus application server, and tests the Orders Web Panel to confirm the new field appears in the form, is required on Save, and defaults correctly for existing records. Work log: “OrderMgmtKB; Orders Transaction; added ExpectedShipDate attribute (Date domain, Not Null, Default = Today()); regenerated: Orders WebPanel, OrderReport, ProcessPendingOrders Procedure (For Each Orders re-evaluated); DB reorganization: ALTER TABLE Orders ADD ExpectedShipDate DATE NOT NULL DEFAULT GETDATE(); deployed to GeneXus app server; Orders Web Panel tested — field visible, required, default correct; ProcessPendingOrders batch tested — no impact on existing Status update logic; 2.5h.”
GeneXus version migration work — migrating an Ev3 Knowledge Base to GeneXus 17 is the highest-stakes and highest-hour GeneXus retainer engagement category, typically arising when a client needs cloud deployment capabilities, REST API publishing, or Smart Device (iOS/Android) app generation that their current Ev3 Knowledge Base cannot provide. The retainer developer begins with a migration impact assessment: export the Ev3 Knowledge Base to .xpz format, import it into a GeneXus 17 evaluation installation, and run the Knowledge Base consistency checker to identify deprecated object types and unsupported patterns. Common migration issues include: Classic Web Panels (the Ev3 web UI generation model using GeneXus’s older “classic” HTML rendering) must be converted to Web Panels with responsive web framework (GeneXus 17 defaults to the Angular-based GeneXus Framework for web UI generation); this conversion requires reviewing every Web Panel’s event code for patterns that relied on classic-mode postback behavior and rewriting them for the asynchronous event model. Data Provider object patterns that used direct Transaction navigation sometimes need refactoring for GeneXus 17’s updated query optimizer. The critical commitment control change to validate during migration: GeneXus 17 enforces stricter transaction scope isolation for Procedures called from Web Panel events, which can surface latent For Each Update deferred commit lock-hold bugs that were tolerable in Ev3 due to shorter batch durations on smaller data volumes — the migration is the correct moment to audit and fix all such Procedures. Work log: “OrderMgmtKB Ev3 → GeneXus 17 migration; KB consistency check: 12 Classic Web Panels flagged for conversion to responsive framework, 3 Procedures with deprecated call syntax, 2 Data Providers with query optimizer warnings; For Each Update lock audit: 4 Procedures with Commit on Exit = Yes and For Each Update over large tables — all 4 fixed with explicit Commit() calls; Classic Web Panel conversion: 8 of 12 converted this session; event pattern rewrite for async model: OrderSearch, OrderDetail, OrderEntry Web Panels; 8h.”
Track GeneXus developer retainer hours without the status emails
When a 4-hour investigation traces 8–12 lock-wait timeout errors per nightly batch run to a GeneXus ProcessPendingOrders Procedure that holds 500 SQL Server UPDATE row-level locks for the full 40-minute batch duration — because Commit on Exit = Yes defers all 500 For Each Update row-level locks until Procedure exit — the work log must name the Procedure, the Commit on Exit setting, the order count, the batch duration, the lock count at peak, and the lock-wait timeout count before and after the Commit() fix inside the loop. HourTab gives your GeneXus retainer client a public dashboard URL they can bookmark: hours used, hours remaining, and a work log naming the per-iteration Commit() fix. No client login. No status emails. CSV in, URL out.
How HourTab tracks GeneXus developer retainer hours
GeneXus For Each Update deferred commit lock-hold bugs are invisible in development by exactly the mechanism that makes all production-scale lock bugs invisible in small-data testing environments. The developer who tests ProcessPendingOrders against a 10-order test set in GeneXus Studio sees the Procedure complete in under 3 seconds; no concurrent users are present in the development environment; no lock-wait errors appear in any log. GeneXus Studio’s built-in test runner does not display a “locks currently held” counter or alert the developer that 10 UPDATE row-level locks are accumulating inside the active transaction. The GeneXus-generated SQL with its UPDLOCK hints is visible only if the developer explicitly enables SQL trace output and examines the generated SQL text — a non-default configuration that most GeneXus developers do not use during functional testing of a batch Procedure. The lock accumulation is entirely invisible to the developer at test time. In production, the lock-hold pattern emerges only when two conditions are simultaneously true: the pending order count is large enough that the batch duration extends to tens of minutes, and concurrent users on the night shift attempt to access the locked order records. Neither condition is present in a development environment. The first production incident is typically reported as an intermittent database error, resolved by operator retry (because by the time the operator retries, the batch has either finished and committed or the specific order they needed has already been processed), which causes the incident to be closed without root-cause investigation.
The work log entry that makes GeneXus For Each Update lock work auditable must name every element of the causal chain. The Knowledge Base name and GeneXus version (OrderMgmtKB, GeneXus Ev3). The Procedure name and its Commit on Exit setting (ProcessPendingOrders, Commit on Exit = Yes). The For Each target table and Where clause (For Each Orders Where Status = 'Pending'). The production row count at batch time (500 pending orders at 11 PM). The batch duration under production load (40 minutes). The peak lock count as measured by the DMV query (500 RID locks on the Orders table in session held by DOMAIN\gxappservice). The lock-wait timeout error rate before fix (8–12 SQL Server error 1222 reports per batch run). The fix applied (explicit Commit() call inserted inside For Each loop after Orders.Status = 'Processing' assignment). The lock-hold duration per iteration after fix (milliseconds, released immediately after each Commit()). The error rate after fix (0 lock-wait timeout errors per batch run). Hours (4h). A log entry that says “fixed database locking issue in batch job, 4h” is not auditable and is not defensible to the client’s IT director, operations manager, or the development team that inherited the Knowledge Base. A log entry that names the Procedure, the commit model, the lock count, the duration, and the before/after error rate is auditable, defensible, and builds the trust that sustains a long-term GeneXus retainer relationship. HourTab gives GeneXus developers a public retainer-hours URL they send to clients — manufacturing companies, government agencies, financial institutions, and logistics companies in Latin America and Japan that built core business systems in GeneXus during the Ev1/Ev2/Ev3 era and maintain them today with a GeneXus specialist on retainer.
The broader context for GeneXus retainer billing is that the deferred commit lock-hold pattern is not unique to GeneXus — it is the universal consequence of implicit transaction management in platform-generated code where the developer describes the business operation and the platform decides the transaction boundary. Magic xpa developer retainers cover the Magic xpa implicit transaction model and the “Quit task without Rollback” lock-hold pattern — the same implicit transaction lock accumulation where a Magic xpa Main Program iterates over records and holds all row-level locks until task exit, structurally identical to GeneXus’s For Each Update deferred commit model. Progress OpenEdge ABL developer retainers cover the Progress ABL FIND FIRST ... EXCLUSIVE-LOCK without RELEASE pattern — the same lock not released on the failure branch, the same production lock-wait errors invisible in single-user development testing, the same root cause (implicit lock held beyond the minimum necessary scope). Uniface developer retainers cover the Uniface TCC (Transaction Commit Control) driver implicit lock — the same platform-managed implicit transaction lock where the Uniface runtime holds all modified record locks until the TCC driver fires its commit, structurally analogous to GeneXus’s Commit on Exit = Yes deferred commit model. In each case, the retainer developer’s value is the same: understanding the platform’s implicit transaction model, diagnosing the lock accumulation in production via DBMS system views, and adding the correct explicit commit or release call in the right location in the platform-specific code.
FAQ: GeneXus developer retainers
What does a GeneXus developer on retainer typically do?
A GeneXus developer on monthly retainer covers For Each Update deferred commit lock-hold audits (reviewing every batch Procedure that uses a For Each Update loop to confirm that Commit on Exit behavior does not accumulate long-duration row-level locks under production data volumes); lock-wait timeout diagnosis (querying sys.dm_tran_locks joined to sys.dm_exec_sessions to identify which GeneXus Procedure holds the lock set, using sys.dm_exec_sql_text to confirm the GeneXus-generated UPDATE with UPDLOCK hint, and adding an explicit Commit() call inside the For Each loop to release locks per iteration); GeneXus Knowledge Base maintenance (adding attributes to Transactions, updating validation rules, modifying Procedure logic, regenerating affected objects without triggering unnecessary regeneration of unrelated components); GeneXus version migration work (migrating Ev1/Ev2/Ev3 Knowledge Bases to GeneXus 15, 16, or 17, handling deprecated object types, updating Web Panel event patterns for the new HTTP/2 web framework, and validating generated code differences); and GeneXus API publishing and cloud deployment configuration for GeneXus 16 and 17 environments targeting AWS, Azure, or Google Cloud.
What GeneXus lock debugging work is most commonly underlogged?
For Each Update deferred commit lock-hold bugs in batch Procedures are the most systematically underlogged GeneXus retainer work. The pattern: a GeneXus Procedure with Commit on Exit = Yes uses a For Each Orders Where Status = 'Pending' / Update block; in development testing against 10 orders the batch completes in under 3 seconds and no lock-wait errors are observed; in production against 500 orders the batch holds 500 SQL Server UPDATE row-level locks for the full 40-minute batch duration; concurrent order-entry users receive SQL Server error 1222 (lock-wait timeout exceeded); GeneXus Studio shows no indication that locks are accumulating; the GeneXus web application displays a generic “Error accessing database” message that does not name ProcessPendingOrders as the lock holder; the DBA must query sys.dm_exec_sessions joined to sys.dm_tran_locks and trace the session to the JDBC connection pool used by the GeneXus application server to identify the holding Procedure. The work log must name the Procedure, the Commit on Exit setting, the For Each Update target table, the order row count, the batch duration, the lock count at peak, and the lock-wait timeout count before and after the Commit() fix.
What are typical GeneXus developer retainer rates?
Entry-level GeneXus developers with experience in GeneXus Transaction objects, basic Procedure coding, For Each navigation, and Web Panel event scripting typically bill at $60 to $105 per hour. Mid-level GeneXus developers with experience in GeneXus Commit on Exit configuration, explicit Commit() and Rollback() calls, Data Provider objects, GeneXus REST API publishing, and Knowledge Base reorganization across multiple Transactions and Procedures typically bill at $90 to $155 per hour. Senior GeneXus developers with deep knowledge of GeneXus-generated SQL for SQL Server, Oracle, and PostgreSQL backends (including UPDLOCK hints in For Each Update, SQL Server lock escalation thresholds, and deferred transaction semantics), GeneXus version migration from Ev1/Ev2/Ev3 to GeneXus 15/16/17, GeneXus Smart Device generator, and production lock forensics via SQL Server DMVs typically bill at $130 to $230 per hour. Monthly retainer ranges: $1,800 to $3,500 per month for advisory engagements covering Knowledge Base health reviews and lock audit consulting; $3,000 to $5,500 per month for active Knowledge Base maintenance, Procedure development, and version migration work.
What should a GeneXus developer retainer agreement include?
A GeneXus developer retainer agreement should specify: GeneXus version (GeneXus Ev1, Ev2, Ev3, GeneXus 15, 16, or 17 — each version has different object types, web framework generators, and API publishing capabilities); the Knowledge Base generator in use (Java or .NET for web, Smart Device for iOS/Android, RPG for AS/400); the backend DBMS (SQL Server, Oracle, PostgreSQL, MySQL, or DB2 — GeneXus-generated SQL differs significantly across backends, particularly for For Each Update UPDLOCK versus SELECT FOR UPDATE syntax); whether the retainer developer has access to the GeneXus Knowledge Base (.xpz export or live KB connection — required to modify Procedures and regenerate objects); whether the retainer covers deferred commit lock-hold analysis for batch Procedures (reviewing every Procedure with Commit on Exit = Yes that uses For Each Update over large tables for production-scale lock accumulation risk); the scope of Knowledge Base reorganization (whether adding attributes to a Transaction requires review of all generated Web Panels and Reports that reference the affected Transaction); and whether the retainer includes GeneXus version migration scoping for clients running Ev1/Ev2/Ev3 Knowledge Bases who need to move to GeneXus 17 for cloud deployment and API publishing support.
How should GeneXus developer retainer hours be logged?
Log each GeneXus retainer session with the Knowledge Base name, the GeneXus object type (Procedure, Transaction, Web Panel, Data Provider), the specific issue, and the before/after outcome metric. For For Each Update deferred commit lock hold: Knowledge Base (OrderMgmtKB), Procedure (ProcessPendingOrders), Commit on Exit setting (Yes), For Each target table (Orders), Where clause (Status = ‘Pending’), production order count at batch time (500), batch duration (40 minutes), SQL Server row-level UPDATE lock count at peak (500 RIDs held by session DOMAIN\gxappservice), lock-wait timeout errors per batch run before fix (8–12, SQL Server error 1222), fix (explicit Commit() call inserted inside For Each loop after Orders.Status = 'Processing' assignment), lock hold per iteration after fix (released immediately after each Commit()), lock-wait timeout errors after fix (0), hours (4h). For Knowledge Base attribute addition: KB name, Transaction modified, new attribute name and type, affected Procedure/Web Panel/Report count regenerated, DB reorganization SQL generated, test coverage, hours. For version migration: source GeneXus version (Ev3), target version (GeneXus 17), deprecated object types handled, Web Panel event pattern changes, For Each Update lock audit performed, test matrix, hours.