<TABLE> <S> <C>

<PAGE>
<ARTICLE> 5
<LEGEND>
THIS SCHEDULE CONTAINS SUMMARY FINANCIAL INFORMATION EXTRACTED FROM THE
CONSOLIDATED FINANCIAL STATEMENTS FOR THE YEARS ENDED DECEMBER 31, 1999, 1998,
AND 1997 AND IS QUALIFIED IN ITS ENTIRETY BY REFERENCE TO SUCH FINANCIAL
STATEMENTS.
</LEGEND>
<MULTIPLIER> 1,000

<S>                             <C>                     <C>                     <C>
<PERIOD-TYPE>                   YEAR                   YEAR                   YEAR
<FISCAL-YEAR-END>                          DEC-31-1999             DEC-31-1998             DEC-31-1997
<PERIOD-START>                             JAN-01-1999             JAN-01-1998             DEC-31-1997
<PERIOD-END>                               DEC-31-1999             DEC-31-1998             DEC-31-1997
<CASH>                                           1,338                   1,499                   1,711
<SECURITIES>                                         0                       0                       0
<RECEIVABLES>                                   11,887                  10,548                  10,110
<ALLOWANCES>                                       489                     424                     338
<INVENTORY>                                          0                       0                       0
<CURRENT-ASSETS>                                16,325                  13,934                  13,270
<PP&E>                                           9,091                   6,892                   5,229
<DEPRECIATION>                                   3,376                   4,133                   3,402
<TOTAL-ASSETS>                                  33,662                  22,423                  21,040
<CURRENT-LIABILITIES>                           13,505                  10,947                   9,460
<BONDS>                                          2,523                     454                     489
<PREFERRED-MANDATORY>                                0                       0                       0
<PREFERRED>                                        242                     242                     242
<COMMON>                                        49,175                  42,546                  42,080
<OTHER-SE>                                    (31,783)                (31,766)                (31,231)
<TOTAL-LIABILITY-AND-EQUITY>                    33,662                  22,423                  21,040
<SALES>                                         51,452                  48,545                  40,795
<TOTAL-REVENUES>                                51,452                  48,545                  40,795
<CGS>                                           35,633                  33,535                  27,479
<TOTAL-COSTS>                                   35,633                  33,535                  27,479
<OTHER-EXPENSES>                                   716                   1,121                     784
<LOSS-PROVISION>                                     0                       0                       0
<INTEREST-EXPENSE>                                 378                     287                     263
<INCOME-PRETAX>                                  1,336                   (272)                   2,023
<INCOME-TAX>                                       620                     546                     435
<INCOME-CONTINUING>                                716                   (818)                   1,588
<DISCONTINUED>                                       0                       0                       0
<EXTRAORDINARY>                                      0                       0                       0
<CHANGES>                                            0                       0                       0
<NET-INCOME>                                       716                   (818)                   1,588
<EPS-BASIC>                                       0.03                  (0.03)                    0.09
<EPS-DILUTED>                                     0.03                  (0.03)                    0.06


</TABLE>